diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacer.java b/src/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacer.java
index fd78537f9..79e4ccdc5 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacer.java
@@ -20,6 +20,21 @@
 public class KeywordReplacer
     implements Replacer
 {
+    /**
+     * Index of the optional prefix group in the regex.
+     */
+    private static final int INDEX_OPTIONAL_PREFIX_GROUP = 1;
+
+    /**
+     * Index of the keyword match group in the regex.
+     */
+    private static final int INDEX_KEYWORD_MATCH_GROUP = 2;
+
+    /**
+     * Index of the optional suffix group in the regex.
+     */
+    private static final int INDEX_OPTIONAL_SUFFIX_GROUP = 3;
+
     /**
      * The keyword to highlight.
      */
@@ -65,15 +80,17 @@ public void replace(final StringBuilder target, final String piece)
         }
 
         final Matcher m =
-            Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE)
-                .matcher(piece);
+            Pattern.compile("(^|\\W)(" + Pattern.quote(keyword) + ")(\\W|$)",
+                Pattern.CASE_INSENSITIVE).matcher(piece);
         int prevEnd = 0;
         while (m.find())
         {
             target.append(StringEscapeUtils.escapeHtml4(piece.substring(
-                prevEnd, m.start())));
-            prevEnd = m.end();
-            final String keywordMatch = m.group().trim();
+                prevEnd, m.start()
+                    + m.group(INDEX_OPTIONAL_PREFIX_GROUP).length())));
+            prevEnd = m.end() - m.group(INDEX_OPTIONAL_SUFFIX_GROUP).length();
+            final String keywordMatch =
+                m.group(INDEX_KEYWORD_MATCH_GROUP).trim();
             target.append("");
             target.append(StringEscapeUtils.escapeHtml4(keywordMatch));
             target.append("");
diff --git a/test/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacerTest.java b/test/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacerTest.java
new file mode 100644
index 000000000..97a660ed8
--- /dev/null
+++ b/test/net/java/sip/communicator/impl/gui/main/chat/replacers/KeywordReplacerTest.java
@@ -0,0 +1,143 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.chat.replacers;
+
+import junit.framework.*;
+
+/**
+ * Tests for keyword replacer.
+ *
+ * @author Danny van Heumen
+ */
+public class KeywordReplacerTest
+    extends TestCase
+{
+    public void testConstructWithoutKeyword()
+    {
+        new KeywordReplacer(null);
+    }
+
+    public void testConstructEmptyKeyword()
+    {
+        new KeywordReplacer("");
+    }
+
+    public void testConstructWithKeyword()
+    {
+        new KeywordReplacer("keyword");
+    }
+
+    public void testExpectPlainText()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("test");
+        Assert.assertTrue(replacer.expectsPlainText());
+    }
+
+    public void testNullKeywordReplacement()
+    {
+        KeywordReplacer replacer = new KeywordReplacer(null);
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "this is a piece of text");
+        Assert.assertEquals("this is a piece of text", target.toString());
+    }
+
+    public void testEmptyKeywordReplacement()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "this is a piece of text");
+        Assert.assertEquals("this is a piece of text", target.toString());
+    }
+
+    public void testTrivialKeywordReplace()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "word");
+        Assert.assertEquals("word", target.toString());
+    }
+
+    public void testKeywordTooSmallForReplacement()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "wor");
+        Assert.assertEquals("wor", target.toString());
+    }
+
+    public void testKeywordInSentence()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "some word in a sentence");
+        Assert.assertEquals("some word in a sentence", target.toString());
+    }
+
+    public void testKeywordAtSentenceStart()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "word first in a sentence");
+        Assert.assertEquals("word first in a sentence", target.toString());
+    }
+
+    public void testKeywordAtSentenceEnd()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "last in a sentence word");
+        Assert.assertEquals("last in a sentence word", target.toString());
+    }
+
+    public void testKeywordInSentenceMultipleHits()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "1 word 2 word 3 word 4");
+        Assert.assertEquals("1 word 2 word 3 word 4", target.toString());
+    }
+
+    public void testDontReplaceKeywordInsideWord()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "A sentence containing keywords.");
+        Assert.assertEquals("A sentence containing keywords.", target.toString());
+    }
+
+    public void testDontReplaceKeywordHeadingWord()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "I am the wordsmith.");
+        Assert.assertEquals("I am the wordsmith.", target.toString());
+    }
+
+    public void testDontReplaceKeywordTrailingWord()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "Don't find the word in keyword.");
+        Assert.assertEquals("Don't find the word in keyword.", target.toString());
+    }
+
+    public void testReplaceKeywordAllowPunctuation()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("word");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "Find the hidden word, word. (word) between parentheses.");
+        Assert.assertEquals("Find the hidden word, word. (word) between parentheses.", target.toString());
+    }
+
+    public void testReplaceKeywordAllowPunctuation2()
+    {
+        KeywordReplacer replacer = new KeywordReplacer("fo");
+        StringBuilder target = new StringBuilder();
+        replacer.replace(target, "fo: Whenever someone writes \"for\" or any other word that starts with \"fo\" it recognizes it as my nickname ...");
+        Assert.assertEquals("fo: Whenever someone writes "for" or any other word that starts with "fo" it recognizes it as my nickname ...", target.toString());
+    }
+}