diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -485,10 +485,6 @@ def templatelabel(context, mapping, args
         # i18n: "label" is a keyword
         raise error.ParseError(_("label expects two arguments"))
 
-    # add known effects to the mapping so symbols like 'red', 'bold',
-    # etc. don't need to be quoted
-    mapping.update(dict([(k, k) for k in _effects]))
-
     thing = templater.evalstring(context, mapping, args[1])
 
     # apparently, repo could be a string that is the favicon?
@@ -496,7 +492,9 @@ def templatelabel(context, mapping, args
     if isinstance(repo, str):
         return thing
 
-    label = templater.evalstring(context, mapping, args[0])
+    # preserve unknown symbol as literal so effects like 'red', 'bold',
+    # etc. don't need to be quoted
+    label = templater.evalstringliteral(context, mapping, args[0])
 
     return repo.ui.label(thing, label)
 
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -231,6 +231,16 @@ def evalstring(context, mapping, arg):
     func, data = arg
     return stringify(func(context, mapping, data))
 
+def evalstringliteral(context, mapping, arg):
+    """Evaluate given argument as string template, but returns symbol name
+    if it is unknown"""
+    func, data = arg
+    if func is runsymbol:
+        thing = func(context, mapping, data, default=data)
+    else:
+        thing = func(context, mapping, data)
+    return stringify(thing)
+
 def runinteger(context, mapping, data):
     return int(data)
 
@@ -245,7 +255,7 @@ def _recursivesymbolblocker(key):
 def _runrecursivesymbol(context, mapping, key):
     raise error.Abort(_("recursive reference '%s' in template") % key)
 
-def runsymbol(context, mapping, key):
+def runsymbol(context, mapping, key, default=''):
     v = mapping.get(key)
     if v is None:
         v = context._defaults.get(key)
@@ -257,7 +267,7 @@ def runsymbol(context, mapping, key):
         try:
             v = context.process(key, safemapping)
         except TemplateNotFound:
-            v = ''
+            v = default
     if callable(v):
         return v(**mapping)
     return v
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -3178,6 +3178,11 @@ Test recursive evaluation:
   $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
   \x1b[0;32mtext\x1b[0m (esc)
 
+color effect can be specified without quoting:
+
+  $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
+  \x1b[0;31mtext\x1b[0m (esc)
+
 Test branches inside if statement:
 
   $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'