diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 63382f8..5b5bc2b 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -181,6 +181,11 @@ class WikiController < ApplicationController
       export = render_to_string :action => 'export_multiple', :layout => false
       send_data(export, :type => 'text/html', :filename => "wiki.html")
       return      
+    when 'category'
+      @category = params[:category].gsub(/_/, ' ')
+      @pages = @wiki.find_pages_in_category(@category)
+    when 'category_index'
+      @categories = @wiki.find_all_categories
     else
       # requested special page doesn't exist, redirect to default page
       redirect_to :action => 'index', :id => @project, :page => nil and return
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index bab8830..5e527b8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -396,6 +396,32 @@ module ApplicationHelper
 
     project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
 
+    # Wiki category links
+    #
+    # Examples:
+    #   [[category:mycategory]]
+    #   [[category:mycategory|mytext]]
+    # wiki links can refer other project wikis, using project name or identifier:
+    #   [[myproject:category:mycategory]]
+    #   [[myproject:category:mycategory|mytext]]
+    text = text.gsub(/(!)?(\[\[(?:(.+?):)?category:(.+?)(?:\|(.+?))?\]\])/) do |m|
+      esc, all, link_project, category, title = $1, $2, $3, $4, $5
+      if esc.nil?
+        if link_project.nil?
+          link_project = project
+        else
+          link_project = Project.find_by_name(link_project) || Project.find_by_identifier(link_project)
+        end
+        if link_project && link_project.wiki
+          link_to((title || category), :only_path => only_path, :controller => 'wiki', :id => project, :action => 'special', :page => 'category', :category => Wiki.titleize(category))
+        else
+          all
+        end
+      else
+        '!' + all
+      end
+    end
+
     # Wiki links
     #
     # Examples:
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index b31b034..628b9ca 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -44,7 +44,27 @@ class Wiki < ActiveRecord::Base
     end
     page
   end
-  
+
+  # Find pages which belong to a certain category.
+  # Special category 'None' contains all pages with no particular category set.
+  def find_pages_in_category(category)
+    if category == 'None'
+      pages.find :all, :conditions => "categories = '' OR categories IS NULL", :order=> 'title'
+    else
+      pages.find :all, :conditions => [ "LOWER(categories) LIKE LOWER(?)", "%|#{category.downcase}|%"], :order=> 'title'
+    end
+  end
+
+  # Traverse all pages and compile a list of categories.
+  def find_all_categories
+    categories = {}
+    groups = pages.find :all, :select => :categories, :conditions => "categories != ''", :group => :categories
+    groups.map {|c| c.categories[1..-2].split('|') }.flatten.sort.each do |g|
+      categories[g.downcase] = g   # case insensitive uniq
+    end
+    categories.values
+  end
+
   # Finds a page by title
   # The given string can be of one of the forms: "title" or "project:title"
   # Examples:
@@ -63,13 +83,17 @@ class Wiki < ActiveRecord::Base
       end
     end
   end
-  
+
+  # Upcase only the first letter of a title
+  def self.upcase_first(title='')
+    title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
+  end
+
   # turn a string into a valid page title
   def self.titleize(title)
     # replace spaces with _ and remove unwanted caracters
     title = title.gsub(/\s+/, '_').delete(',./?;|:') if title
-    # upcase the first letter
-    title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
+    title = self.upcase_first(title)
     title
   end  
 end
diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb
index 372ca83..817092f 100644
--- a/app/models/wiki_content.rb
+++ b/app/models/wiki_content.rb
@@ -25,10 +25,24 @@ class WikiContent < ActiveRecord::Base
   validates_length_of :comments, :maximum => 255, :allow_nil => true
   
   acts_as_versioned
-    
+
+  def after_save
+    page.categories = categories.join('|')
+    page.categories = '|' + page.categories + '|' if !categories.empty? 
+    page.save!
+  end
+
   def project
     page.project
   end
+
+  def categories
+    if text.match(/\{\{categor(?:y|ies)\((.+?)\)\}\}/)
+      $1.split(/\s*,\s*/).map { |c| Wiki.upcase_first(c) }
+    else
+      []
+    end
+  end
   
   class Version
     belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
diff --git a/app/views/wiki/_sidebar.rhtml b/app/views/wiki/_sidebar.rhtml
index 20c0871..4d18c53 100644
--- a/app/views/wiki/_sidebar.rhtml
+++ b/app/views/wiki/_sidebar.rhtml
@@ -3,3 +3,13 @@
 <%= link_to l(:field_start_page), {:action => 'index', :page => nil} %><br />
 <%= link_to l(:label_index_by_title), {:action => 'special', :page => 'Page_index'} %><br />
 <%= link_to l(:label_index_by_date), {:action => 'special', :page => 'Date_index'} %><br />
+<%= link_to l(:label_index_by_category), {:action => 'special', :page => 'Category_index'} %><br />
+
+<% if wiki_categories = @page.categories.sub(/^\|(.*)\|$/, '\1').split('|') rescue nil %>
+  <% if (!wiki_categories.empty?) %>
+    <h3><%= l((wiki_categories.length==1)?(:label_wiki_category):(:label_wiki_category_plural)) %></h3>
+    <% wiki_categories.sort.each do |category| %>
+      <%= link_to category, {:action => 'special', :page => 'category', :category => Wiki.titleize(category)} %><br />
+    <% end %>
+  <% end %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/wiki/special_category.rhtml b/app/views/wiki/special_category.rhtml
new file mode 100644
index 0000000..cc1f943
--- /dev/null
+++ b/app/views/wiki/special_category.rhtml
@@ -0,0 +1,27 @@
+<% if @category == 'None' %>
+  <h2><%= l(:label_pages_without_category) %></h2>
+<% else %>
+  <h2><%= l(:label_wiki_category) %>: <%= @category %></h2>
+<% end %>
+
+<% if @pages.empty? %>
+  <p class="nodata"><%= l(:label_no_data) %></p>
+<% end %>
+
+<% content_for :sidebar do %>
+  <%= render :partial => 'sidebar' %>
+<% end %>
+
+<% unless @pages.empty? %>
+  <p>
+    <ul>
+      <% group = nil %>
+      <% @pages.each do |page| %>
+        <% if page.title[0,1].upcase != group %>
+          </ul><h4><%= group = page.title[0,1].upcase %></h4><ul>
+        <% end %>
+        <li><%= link_to page.pretty_title, {:action => 'index', :page => page.title} %></li>
+      <% end %>
+    </ul>
+  </p>
+<% end %>
\ No newline at end of file
diff --git a/app/views/wiki/special_category_index.rhtml b/app/views/wiki/special_category_index.rhtml
new file mode 100644
index 0000000..319e63b
--- /dev/null
+++ b/app/views/wiki/special_category_index.rhtml
@@ -0,0 +1,28 @@
+<h2><%= l(:label_index_by_category) %></h2>
+
+<% content_for :sidebar do %>
+  <%= render :partial => 'sidebar' %>
+<% end %>
+
+<% unless @categories.empty? %>
+  <p>
+    <ul>
+      <% group = nil %>
+      <% @categories.each do |category| %>
+        <% if category[0,1].upcase != group %>
+          </ul><h4><%= group = category[0,1].upcase %></h4><ul>
+        <% end %>
+        <li><%= link_to category, {:action => 'special', :page => 'category', :category => category} %></li>
+      <% end %>
+    </ul>
+  </p>
+<% end %>
+
+<h4><%= l(:label_special) %></h4>
+<p>
+  <ul>
+    <li>
+      <%= link_to l(:label_pages_without_category), {:action => 'special', :page => 'category', :category => 'None'} %>
+    </li>
+  </ul>
+</p>
\ No newline at end of file
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 46551d6..fbb5ee6 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -448,8 +448,13 @@ bg:
   label_wiki_edit_plural: Wiki редакции
   label_wiki_page: Wiki page
   label_wiki_page_plural: Wiki pages
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Индекс
   label_index_by_date: Индекс по дата
+  label_index_by_category: Index by category
   label_current_version: Текуща версия
   label_preview: Преглед
   label_feed_plural: Feeds
diff --git a/config/locales/bs.yml b/config/locales/bs.yml
index d746048..c14d1ea 100644
--- a/config/locales/bs.yml
+++ b/config/locales/bs.yml
@@ -597,8 +597,13 @@ bs:
   label_wiki_edit_plural: ispravke wiki-ja
   label_wiki_page: Wiki stranica
   label_wiki_page_plural: Wiki stranice
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Indeks prema naslovima
   label_index_by_date: Indeks po datumima
+  label_index_by_category: Index by category
   label_current_version: Tekuća verzija
   label_preview: Pregled
   label_feed_plural: Feeds
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 24bb33e..9c0e449 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -577,8 +577,13 @@ ca:
   label_wiki_edit_plural: Edicions wiki
   label_wiki_page: Pàgina wiki
   label_wiki_page_plural: Pàgines wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Índex per títol
   label_index_by_date: Índex per data
+  label_index_by_category: Index by category
   label_current_version: Versió actual
   label_preview: Previsualització
   label_feed_plural: Canals
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index c1c429d..be8514a 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -506,8 +506,13 @@ cs:
   label_wiki_edit_plural: Wiki úpravy
   label_wiki_page: Wiki stránka
   label_wiki_page_plural: Wiki stránky
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Index dle názvu
   label_index_by_date: Index dle data
+  label_index_by_category: Index by category
   label_current_version: Aktuální verze
   label_preview: Náhled
   label_feed_plural: Příspěvky
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 7ebea2c..9a2d7e2 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -517,8 +517,13 @@ da:
   label_wiki_edit_plural: Wiki ændringer
   label_wiki_page: Wiki side
   label_wiki_page_plural: Wiki sider
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Indhold efter titel
   label_index_by_date: Indhold efter dato
+  label_index_by_category: Index by category
   label_current_version: Nuværende version
   label_preview: Forhåndsvisning
   label_feed_plural: Feeds
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 8f99608..656e481 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -592,8 +592,13 @@ de:
   label_wiki_edit_plural: Wiki-Bearbeitungen
   label_wiki_page: Wiki-Seite
   label_wiki_page_plural: Wiki-Seiten
+  label_wiki_category: Kategorie
+  label_wiki_category_plural: Kategorien
+  label_special: Speziell
+  label_pages_without_category: Seiten ohne Kategorie
   label_index_by_title: Seiten nach Titel sortiert
   label_index_by_date: Seiten nach Datum sortiert
+  label_index_by_category: Seiten nach Kategorie sortiert
   label_current_version: Gegenwärtige Version
   label_preview: Vorschau
   label_feed_plural: Feeds
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 6147bd5..976d2e6 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -595,8 +595,13 @@ el:
   label_wiki_edit_plural: Επεξεργασία wiki
   label_wiki_page: Σελίδα Wiki
   label_wiki_page_plural: Σελίδες Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Δείκτης ανά τίτλο
   label_index_by_date: Δείκτης ανά ημερομηνία
+  label_index_by_category: Index by category
   label_current_version: Τρέχουσα έκδοση
   label_preview: Προεπισκόπηση
   label_feed_plural: Feeds
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 71e599a..1abb06c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -594,8 +594,13 @@ en:
   label_wiki_edit_plural: Wiki edits
   label_wiki_page: Wiki page
   label_wiki_page_plural: Wiki pages
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Index by title
   label_index_by_date: Index by date
+  label_index_by_category: Index by category
   label_current_version: Current version
   label_preview: Preview
   label_feed_plural: Feeds
diff --git a/config/locales/es.yml b/config/locales/es.yml
index e76929d..ebddecd 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -462,6 +462,7 @@ es:
   label_incoming_emails: Correos entrantes
   label_index_by_date: Índice por fecha
   label_index_by_title: Índice por título
+  label_index_by_category: Índice por categoría
   label_information: Información
   label_information_plural: Información
   label_integer: Número
@@ -647,6 +648,10 @@ es:
   label_wiki_edit_plural: Wiki edicciones
   label_wiki_page: Wiki página
   label_wiki_page_plural: Wiki páginas
+  label_wiki_category: Categoría
+  label_wiki_category_plural: Categorías
+  label_special: Especial
+  label_pages_without_category: Páginas sin categoría
   label_workflow: Flujo de trabajo
   label_year: Año
   label_yesterday: ayer
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index fffddc6..e990e28 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -506,8 +506,13 @@ fi:
   label_wiki_edit_plural: Wiki muokkaukset
   label_wiki_page: Wiki sivu
   label_wiki_page_plural: Wiki sivut
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Hakemisto otsikoittain
   label_index_by_date: Hakemisto päivittäin
+  label_index_by_category: Index by category
   label_current_version: Nykyinen versio
   label_preview: Esikatselu
   label_feed_plural: Syötteet
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 82936b4..2672f2a 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -611,8 +611,13 @@ fr:
   label_wiki_edit_plural: Révisions wiki
   label_wiki_page: Page wiki
   label_wiki_page_plural: Pages wiki
+  label_wiki_category: Catégorie
+  label_wiki_category_plural: Catégories
+  label_special: Spécial
+  label_pages_without_category: Pages sans catégorie
   label_index_by_title: Index par titre
   label_index_by_date: Index par date
+  label_index_by_category: Index par catégorie
   label_current_version: Version actuelle
   label_preview: Prévisualisation
   label_feed_plural: Flux RSS
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 00bdbbf..1e46b1b 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -441,6 +441,7 @@ gl:
   label_incoming_emails: Correos entrantes
   label_index_by_date: Índice por data
   label_index_by_title: Índice por título
+  label_index_by_category: Index by category
   label_information: Información
   label_information_plural: Información
   label_integer: Número
@@ -626,6 +627,10 @@ gl:
   label_wiki_edit_plural: Wiki edicións
   label_wiki_page: Wiki páxina
   label_wiki_page_plural: Wiki páxinas
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_workflow: Fluxo de traballo
   label_year: Ano
   label_yesterday: onte
diff --git a/config/locales/he.yml b/config/locales/he.yml
index ecf5820..17660b5 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -463,8 +463,13 @@ he:
   label_wiki_edit_plural: עריכות Wiki
   label_wiki_page: דף Wiki
   label_wiki_page_plural: דפי Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: סדר על פי כותרת
   label_index_by_date: סדר על פי תאריך
+  label_index_by_category: Index by category
   label_current_version: גירסא נוכאית
   label_preview: תצוגה מקדימה
   label_feed_plural: הזנות
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 70b0d00..7076c8d 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -533,8 +533,13 @@
   label_wiki_edit_plural: Wiki szerkesztések
   label_wiki_page: Wiki oldal
   label_wiki_page_plural: Wiki oldalak
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Cím szerint indexelve
   label_index_by_date: Dátum szerint indexelve
+  label_index_by_category: Index by category
   label_current_version: Jelenlegi verzió
   label_preview: Előnézet
   label_feed_plural: Visszajelzések
diff --git a/config/locales/it.yml b/config/locales/it.yml
index d51e240..0515a7d 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -461,8 +461,13 @@ it:
   label_wiki_edit_plural: Modfiche wiki
   label_wiki_page: Pagina Wiki
   label_wiki_page_plural: Pagine Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Ordina per titolo
   label_index_by_date: Ordina per data
+  label_index_by_category: Index by category
   label_current_version: Versione corrente
   label_preview: Anteprima
   label_feed_plural: Feed
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 35121b7..6ecc4cd 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -624,8 +624,13 @@ ja:
   label_wiki_edit_plural: Wiki編集
   label_wiki_page: Wikiページ
   label_wiki_page_plural: Wikiページ
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: 索引(名前順)
   label_index_by_date: 索引(日付順)
+  label_index_by_category: Index by category
   label_current_version: 最新版
   label_preview: プレビュー
   label_feed_plural: フィード
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 82ab805..7c8113d 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -648,8 +648,13 @@ ko:
   label_wiki_edit_plural: 위키 편집
   label_wiki_page: 위키 페이지
   label_wiki_page_plural: 위키 페이지
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: 제목별 색인
   label_index_by_date: 날짜별 색인
+  label_index_by_category: Index by category
   label_current_version: 현재 버전
   label_preview: 미리보기
   label_feed_plural: 피드(Feeds)
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index fbe3c67..b3fc6cb 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -601,8 +601,13 @@ lt:
   label_wiki_edit_plural: Wiki redakcijos
   label_wiki_page: Wiki puslapis
   label_wiki_page_plural: Wiki puslapiai
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Indeksas prie pavadinimo
   label_index_by_date: Indeksas prie datos
+  label_index_by_category: Index by category
   label_current_version: Einamoji versija
   label_preview: Peržiūra
   label_feed_plural: Įeitys(Feeds)
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 9f89b81..9e10208 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -403,6 +403,7 @@ nl:
   label_incoming_emails: Inkomende e-mail
   label_index_by_date: Indexeer op datum
   label_index_by_title: Indexeer op titel
+  label_index_by_category: Index by category
   label_information: Informatie
   label_information_plural: Informatie
   label_integer: Integer
@@ -588,6 +589,10 @@ nl:
   label_wiki_edit_plural: Wiki edits
   label_wiki_page: Wikipagina
   label_wiki_page_plural: Wikipagina's
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_workflow: Workflow
   label_year: Jaar
   label_yesterday: gisteren
diff --git a/config/locales/no.yml b/config/locales/no.yml
index c22200c..d4c1dab 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -506,8 +506,13 @@
   label_wiki_edit_plural: Wiki endringer
   label_wiki_page: Wiki-side
   label_wiki_page_plural: Wiki-sider
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Indekser etter tittel
   label_index_by_date: Indekser etter dato
+  label_index_by_category: Index by category
   label_current_version: Gjeldende versjon
   label_preview: Forhåndsvis
   label_feed_plural: Feeder
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 4f6a28c..558a239 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -437,6 +437,7 @@ pl:
   label_incoming_emails: Przychodząca poczta elektroniczna
   label_index_by_date: Indeks wg daty
   label_index_by_title: Indeks
+  label_index_by_category: Index by category
   label_information: Informacja
   label_information_plural: Informacje
   label_integer: Liczba całkowita
@@ -626,6 +627,10 @@ pl:
   label_wiki_edit_plural: Edycje wiki
   label_wiki_page: Strona wiki
   label_wiki_page_plural: Strony wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_workflow: Przepływ
   label_year: Rok
   label_yesterday: wczoraj
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 287a068..9e56b37 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -544,8 +544,13 @@ pt-BR:
   label_wiki_edit_plural: Edições Wiki
   label_wiki_page: Página Wiki
   label_wiki_page_plural: páginas Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Índice por título
   label_index_by_date: Índice por data
+  label_index_by_category: Index by category
   label_current_version: Versão atual
   label_preview: Pré-visualizar
   label_feed_plural: Feeds
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 2086af4..416a0d7 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -531,8 +531,13 @@ pt:
   label_wiki_edit_plural: Edições da Wiki
   label_wiki_page: Página da Wiki
   label_wiki_page_plural: Páginas da Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Índice por título
   label_index_by_date: Índice por data
+  label_index_by_category: Index by category
   label_current_version: Versão actual
   label_preview: Pré-visualizar
   label_feed_plural: Feeds
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index c3b8dd2..baa797f 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -575,8 +575,13 @@ ro:
   label_wiki_edit_plural: Editări Wiki
   label_wiki_page: Pagină Wiki
   label_wiki_page_plural: Pagini Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Sortează după titlu
   label_index_by_date: Sortează după dată
+  label_index_by_category: Index by category
   label_current_version: Versiunea curentă
   label_preview: Previzualizare
   label_feed_plural: Feed-uri
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index c885447..8cebadd 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -505,6 +505,7 @@ ru:
   label_incoming_emails: Приём сообщений
   label_index_by_date: История страниц
   label_index_by_title: Оглавление
+  label_index_by_category: Index by category
   label_information_plural: Информация
   label_information: Информация
   label_in_less_than: менее чем
@@ -699,6 +700,10 @@ ru:
   label_wiki_edit_plural: Wiki
   label_wiki_page: Страница Wiki
   label_wiki_page_plural: Страницы Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_workflow: Последовательность действий
   label_x_closed_issues_abbr:
     zero:  0 закрыто
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 59a5faa..969deca 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -504,8 +504,13 @@ sk:
   label_wiki_edit_plural: Wiki úpravy
   label_wiki_page: Wiki stránka
   label_wiki_page_plural: Wiki stránky
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Index podľa názvu
   label_index_by_date: Index podľa dátumu
+  label_index_by_category: Index by category
   label_current_version: Aktuálna verzia
   label_preview: Náhľad
   label_feed_plural: Príspevky
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index bfc5e08..b00ecf3 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -567,8 +567,13 @@ sl:
   label_wiki_edit_plural: Wiki urejanja
   label_wiki_page: Wiki stran
   label_wiki_page_plural: Wiki strani
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Razvrsti po naslovu
   label_index_by_date: Razvrsti po datumu
+  label_index_by_category: Index by category
   label_current_version: Trenutna verzija
   label_preview: Predogled
   label_feed_plural: RSS viri
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 0f8ed10..7710fea 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -479,8 +479,13 @@
   label_wiki_edit_plural: Wiki promene
   label_wiki_page: Wiki stranica
   label_wiki_page_plural: Wiki stranice
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Indeks po naslovima
   label_index_by_date: Indeks po datumu
+  label_index_by_category: Index by category
   label_current_version: Trenutna verzija
   label_preview: Brzi pregled
   label_feed_plural: Feeds
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index d775e95..ec0660c 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -643,8 +643,13 @@ sv:
   label_wiki_edit_plural: Wikiändringar
   label_wiki_page: Wikisida
   label_wiki_page_plural: Wikisidor
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Innehåll efter titel
   label_index_by_date: Innehåll efter datum
+  label_index_by_category: Index by category
   label_current_version: Nuvarande version
   label_preview: Förhandsgranska
   label_feed_plural: Feeds
diff --git a/config/locales/th.yml b/config/locales/th.yml
index fb6b36e..affaac8 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -504,8 +504,13 @@ th:
   label_wiki_edit_plural: แก้ไข Wiki
   label_wiki_page: หน้า Wiki
   label_wiki_page_plural: หน้า Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: เรียงตามชื่อเรื่อง
   label_index_by_date: เรียงตามวัน
+  label_index_by_category: Index by category
   label_current_version: รุ่นปัจจุบัน
   label_preview: ตัวอย่างก่อนจัดเก็บ
   label_feed_plural: Feeds
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index d51e465..9724f67 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -533,8 +533,13 @@ tr:
   label_wiki_edit_plural: Wiki düzenlemeleri
   label_wiki_page: Wiki sayfası
   label_wiki_page_plural: Wiki sayfaları
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Başlığa göre diz
   label_index_by_date: Tarihe göre diz
+  label_index_by_category: Index by category
   label_current_version: Güncel versiyon
   label_preview: Önizleme
   label_feed_plural: Beslemeler
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index c14f604..0973dc0 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -464,8 +464,13 @@ uk:
   label_wiki_edit_plural: Редагування Wiki 
   label_wiki_page: Сторінка Wiki
   label_wiki_page_plural: Сторінки Wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Індекс за назвою
   label_index_by_date: Індекс за датою
+  label_index_by_category: Index by category
   label_current_version: Поточна версія
   label_preview: Попередній перегляд
   label_feed_plural: Подання
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 766b462..7765692 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -576,8 +576,13 @@ vi:
   label_wiki_edit_plural: Thay đổi wiki
   label_wiki_page: Trang wiki
   label_wiki_page_plural: Trang wiki
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: Danh sách theo tên
   label_index_by_date: Danh sách theo ngày
+  label_index_by_category: Index by category
   label_current_version: Bản hiện tại
   label_preview: Xem trước
   label_feed_plural: Feeds
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index a9cd42e..5c9c870 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -685,8 +685,13 @@
   label_wiki_edit_plural: Wiki 編輯
   label_wiki_page: Wiki 網頁
   label_wiki_page_plural: Wiki 網頁
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: 依標題索引
   label_index_by_date: 依日期索引
+  label_index_by_category: Index by category
   label_current_version: 現行版本
   label_preview: 預覽
   label_feed_plural: Feeds
diff --git a/config/locales/zh.yml b/config/locales/zh.yml
index 596a08d..e787b77 100644
--- a/config/locales/zh.yml
+++ b/config/locales/zh.yml
@@ -617,8 +617,13 @@ zh:
   label_wiki_edit_plural: Wiki 编辑记录
   label_wiki_page: Wiki 页面
   label_wiki_page_plural: Wiki 页面
+  label_wiki_category: Category
+  label_wiki_category_plural: Categories
+  label_special: Special
+  label_pages_without_category: Pages without category
   label_index_by_title: 按标题索引
   label_index_by_date: 按日期索引
+  label_index_by_category: Index by category
   label_current_version: 当前版本
   label_preview: 预览
   label_feed_plural: Feeds
diff --git a/config/routes.rb b/config/routes.rb
index 1e34001..933a3b3 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -49,13 +49,14 @@ ActionController::Routing::Routes.draw do |map|
   map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
   map.with_options :controller => 'wiki' do |wiki_routes|
     wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
-      wiki_views.connect 'projects/:id/wiki/:page', :action => 'special', :page => /page_index|date_index|export/i
+      wiki_views.connect 'projects/:id/wiki/:page', :action => 'special', :page => /page_index|date_index|category_index|export/i
       wiki_views.connect 'projects/:id/wiki/:page', :action => 'index', :page => nil
       wiki_views.connect 'projects/:id/wiki/:page/edit', :action => 'edit'
       wiki_views.connect 'projects/:id/wiki/:page/rename', :action => 'rename'
       wiki_views.connect 'projects/:id/wiki/:page/history', :action => 'history'
       wiki_views.connect 'projects/:id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
       wiki_views.connect 'projects/:id/wiki/:page/annotate/:version', :action => 'annotate'
+      wiki_views.connect 'projects/:id/wiki/category/:category', :action => 'special', :page => 'category'
     end
     
     wiki_routes.connect 'projects/:id/wiki/:page/:action', 
diff --git a/db/migrate/20091023203350_add_wiki_pages_categories.rb b/db/migrate/20091023203350_add_wiki_pages_categories.rb
new file mode 100644
index 0000000..7d90475
--- /dev/null
+++ b/db/migrate/20091023203350_add_wiki_pages_categories.rb
@@ -0,0 +1,9 @@
+class AddWikiPagesCategories < ActiveRecord::Migration
+  def self.up
+    add_column :wiki_pages, :categories, :string
+  end
+
+  def self.down
+    remove_column :wiki_pages, :categories
+  end
+end
\ No newline at end of file
diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb
index 6f8d09d..e29b1df 100644
--- a/lib/redmine/wiki_formatting/macros.rb
+++ b/lib/redmine/wiki_formatting/macros.rb
@@ -116,6 +116,29 @@ module Redmine
         @included_wiki_pages.pop
         out
       end
+
+      desc "Add the current wiki page to a category.\nExample: !{{category(Help)}}"
+      macro :category do |obj, args|
+        ''   # categories are listed in the sidebar
+      end
+
+      desc "Add the current wiki page to several categories.\nExample: !{{categories(Help, Snippets)}}"
+      macro :categories do |obj, args|
+        ''   # categories are listed in the sidebar
+      end
+
+      desc "Display a list of pages which belong to the specified category.\nExample: !{{pages_in_category(Help)}}"
+      macro :pages_in_category do |obj, args|
+        if !args.first.nil?
+          content_tag :ul, :class => :pages_in_category  do
+            @wiki.find_pages_in_category(args.first).map do |p|
+              content_tag :li do
+                link_to p.pretty_title, {:action => 'index', :page => p.title}
+              end 
+            end
+          end
+        end
+      end
     end
   end
 end
diff --git a/public/help/wiki_syntax.html b/public/help/wiki_syntax.html
index 6886f34..ee03cda 100644
--- a/public/help/wiki_syntax.html
+++ b/public/help/wiki_syntax.html
@@ -56,8 +56,12 @@ table td h3 { font-size: 1.2em; text-align: left; }
 <tr><th></th><td>source:some/file</td><td><a href="#">source:some/file</a></td></tr>
 
 <tr><th colspan="3">Inline images</th></tr>
-<tr><th><img src="../images/jstoolbar/bt_img.png" style="border: 1px solid #bbb;" alt="Image" /></th><td>!<em>image_url</em>!</td><td></td></tr>
-<tr><th></th><td>!<em>attached_image</em>!</td><td></td></tr>
+<tr><th><img src="../images/jstoolbar/bt_img.png" style="border: 1px solid #bbb;" alt="Image" /></th><td colspan="2">!<em>image_url</em>!</td></tr>
+<tr><th></th><td colspan="2">!<em>attached_image</em>!</td></tr>
+
+<tr><th colspan="3">Assign to Page Categories</th></tr>
+<tr><th></th><td colspan="2">{{category(My Category)}}</td></tr>
+<tr><th></th><td colspan="2">{{categories(My Cat 1, My Cat 2)}}</td></tr>
 </table>
 
 <p><a href="wiki_syntax_detailed.html" onclick="window.open('wiki_syntax_detailed.html', '', ''); return false;">More Information</a></p>
diff --git a/public/help/wiki_syntax_detailed.html b/public/help/wiki_syntax_detailed.html
index d3b4cb1..1576e26 100644
--- a/public/help/wiki_syntax_detailed.html
+++ b/public/help/wiki_syntax_detailed.html
@@ -206,7 +206,7 @@ To go live, all you need to add is a database and a web server.
 <pre>
 {{toc}} => left aligned toc
 {{>toc}} => right aligned toc
-</pre>
+</pre>    
 
     <h2><a name="12" class="wiki-page"></a>Macros</h2>
 
@@ -243,5 +243,33 @@ To go live, all you need to add is a database and a web server.
 <span class="no"><strong>10</strong></span> <span class="r">end</span>
 </code>
 </pre>
+
+    <h2><a name="14" class="wiki-page"></a>Page Categories</h2>
+    
+    <p>To assign a page to one or more page categories, insert either of the following anywhere
+    on the page:</p>
+
+<pre>
+{{cagetory(My Category)}}
+{{categories(My Category 1, My Category 2)}}
+</pre>
+
+    <p>The above macros don't output anything, but if a page is assigned to one or more page
+    categories, they are listed in the sidebar. Furthermore, these pages can be accessed using
+    the "Index by category" in the sidebar.</p>
+    
+    <p>You can insert a link to a specific page category. Follow this link to get a list of all
+    pages assigned to that page category.</p>
+
+<pre>
+[[category:My Category]]
+</pre>
+
+    <p>Or you can insert a list of pages assigned to a specific page category:</p>
+
+<pre>
+{{pages_in_category(My Category)}}
+</pre>
+
 </body>
 </html>
diff --git a/test/fixtures/wiki_pages.yml b/test/fixtures/wiki_pages.yml
index a0b8b79..c8c84a8 100644
--- a/test/fixtures/wiki_pages.yml
+++ b/test/fixtures/wiki_pages.yml
@@ -6,6 +6,7 @@ wiki_pages_001:
   wiki_id: 1
   protected: true
   parent_id: 
+  categories: |Examples|Documentation|
 wiki_pages_002: 
   created_on: 2007-03-08 00:18:07 +01:00
   title: Another_page
@@ -13,6 +14,7 @@ wiki_pages_002:
   wiki_id: 1
   protected: false
   parent_id: 
+  categories: 
 wiki_pages_003: 
   created_on: 2007-03-08 00:18:07 +01:00
   title: Start_page
@@ -20,6 +22,7 @@ wiki_pages_003:
   wiki_id: 2
   protected: false
   parent_id: 
+  categories: 
 wiki_pages_004: 
   created_on: 2007-03-08 00:18:07 +01:00
   title: Page_with_an_inline_image
@@ -27,6 +30,7 @@ wiki_pages_004:
   wiki_id: 1
   protected: false
   parent_id: 1
+  categories: |Examples| 
 wiki_pages_005: 
   created_on: 2007-03-08 00:18:07 +01:00
   title: Child_1
@@ -34,6 +38,7 @@ wiki_pages_005:
   wiki_id: 1
   protected: false
   parent_id: 2
+  categories: |Examples| 
 wiki_pages_006: 
   created_on: 2007-03-08 00:18:07 +01:00
   title: Child_2
@@ -41,4 +46,5 @@ wiki_pages_006:
   wiki_id: 1
   protected: false
   parent_id: 2
+  categories: |Examples| 
   
\ No newline at end of file
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index cf247db..a39f48a 100644
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -298,6 +298,14 @@ class WikiControllerTest < ActionController::TestCase
       :controller => 'wiki', :action => 'special', :id => '567', :page => 'date_index'
     )
     assert_routing(
+      {:method => :get, :path => '/projects/567/wiki/category_index'},
+      :controller => 'wiki', :action => 'special', :id => '567', :page => 'category_index'
+    )
+    assert_routing(
+      {:method => :get, :path => '/projects/567/wiki/category/Test'},
+      :controller => 'wiki', :action => 'special', :id => '567', :page => 'category', :category => 'Test'
+    )    
+    assert_routing(
       {:method => :get, :path => '/projects/567/wiki/export'},
       :controller => 'wiki', :action => 'special', :id => '567', :page => 'export'
     )
diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb
index 84fc3bd..abe0b10 100644
--- a/test/unit/helpers/application_helper_test.rb
+++ b/test/unit/helpers/application_helper_test.rb
@@ -226,6 +226,14 @@ RAW
       # project does not exist
       '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
       '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
+      # categories
+      '[[category:Test]]' => '<a href="/projects/ecookbook/wiki/category/Test">Test</a>',
+      '[[category:Test|Text]]' => '<a href="/projects/ecookbook/wiki/category/Test">Text</a>',
+      '[[ecookbook:category:Test]]' => '<a href="/projects/ecookbook/wiki/category/Test">Test</a>',
+      '[[ecookbook:category:Test|Text]]' => '<a href="/projects/ecookbook/wiki/category/Test">Text</a>',
+      '[[unknownproject:category:Test]]' => '[[unknownproject:category:Test]]',
+      '[[unknownproject:category:Test|Text]]' => '[[unknownproject:category:Test|Text]]',
+      '![[category:Test]]' => '[[category:Test]]',
     }
     @project = Project.find(1)
     to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
diff --git a/test/unit/wiki_content_test.rb b/test/unit/wiki_content_test.rb
index 372121b..1a6328b 100644
--- a/test/unit/wiki_content_test.rb
+++ b/test/unit/wiki_content_test.rb
@@ -27,7 +27,7 @@ class WikiContentTest < ActiveSupport::TestCase
   
   def test_create
     page = WikiPage.new(:wiki => @wiki, :title => "Page")  
-    page.content = WikiContent.new(:text => "Content text", :author => User.find(1), :comments => "My comment")
+    page.content = WikiContent.new(:text => "{{category(Test)}}Content text", :author => User.find(1), :comments => "My comment")
     assert page.save
     page.reload
     
@@ -35,7 +35,8 @@ class WikiContentTest < ActiveSupport::TestCase
     assert_kind_of WikiContent, content
     assert_equal 1, content.version
     assert_equal 1, content.versions.length
-    assert_equal "Content text", content.text
+    assert_equal "{{category(Test)}}Content text", content.text
+    assert_equal "|Test|", content.page.categories
     assert_equal "My comment", content.comments
     assert_equal User.find(1), content.author
     assert_equal content.text, content.versions.last.text
diff --git a/test/unit/wiki_test.rb b/test/unit/wiki_test.rb
index 6595e6d..6313919 100644
--- a/test/unit/wiki_test.rb
+++ b/test/unit/wiki_test.rb
@@ -43,4 +43,21 @@ class WikiTest < ActiveSupport::TestCase
     assert_equal 'Page_title_with_CAPITALES', Wiki.titleize('page title with CAPITALES')
     assert_equal 'テスト', Wiki.titleize('テスト')
   end
+
+  def test_upcase_first
+    assert_equal 'Page title', Wiki.upcase_first('page title')
+    assert_equal 'テスト', Wiki.titleize('テスト')
+  end
+
+  def test_find_categories
+    @wiki = Wiki.find(1)
+    assert_equal ['Examples', 'Documentation'], @wiki.find_all_categories
+  end
+
+  def test_find_pages_in_category
+    @wiki = Wiki.find(1)
+    assert_equal [1], @wiki.find_pages_in_category('Documentation').map {|c| c.id }.sort
+    assert_equal [1, 4, 5, 6], @wiki.find_pages_in_category('Examples').map {|c| c.id }.sort
+    assert_equal [2], @wiki.find_pages_in_category('None').map {|c| c.id }.sort
+  end
 end

