diff --git a/mercurial/help/templates.txt b/mercurial/help/templates.txt
index a7dd6692e5cb197544578f0c6aa8629ee4debd99_bWVyY3VyaWFsL2hlbHAvdGVtcGxhdGVzLnR4dA==..c1975809a6b5428478ae05326b31bca16bb6d537_bWVyY3VyaWFsL2hlbHAvdGVtcGxhdGVzLnR4dA== 100644
--- a/mercurial/help/templates.txt
+++ b/mercurial/help/templates.txt
@@ -47,6 +47,10 @@
 
 - expr % "{template}"
 
+As seen in the above example, "{template}" is interpreted as a template.
+To prevent it from being interpreted, you can use an escape character "\{"
+or a raw string prefix, "r'...'".
+
 Some sample command line templates:
 
 - Format lists, e.g. files::
diff --git a/mercurial/templater.py b/mercurial/templater.py
index a7dd6692e5cb197544578f0c6aa8629ee4debd99_bWVyY3VyaWFsL3RlbXBsYXRlci5weQ==..c1975809a6b5428478ae05326b31bca16bb6d537_bWVyY3VyaWFsL3RlbXBsYXRlci5weQ== 100644
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -22,7 +22,7 @@
     ")": (0, None, None),
     "integer": (0, ("integer",), None),
     "symbol": (0, ("symbol",), None),
-    "string": (0, ("string",), None),
+    "string": (0, ("template",), None),
     "rawstring": (0, ("rawstring",), None),
     "end": (0, None, None),
 }
@@ -144,7 +144,9 @@
     return context._filters[f]
 
 def gettemplate(exp, context):
-    if exp[0] == 'string' or exp[0] == 'rawstring':
+    if exp[0] == 'template':
+        return compiletemplate(exp[1], context)
+    if exp[0] == 'rawstring':
         return compiletemplate(exp[1], context, strtoken=exp[0])
     if exp[0] == 'symbol':
         return context._load(exp[1])
@@ -174,6 +176,12 @@
         v = list(v)
     return v
 
+def buildtemplate(exp, context):
+    ctmpl = compiletemplate(exp[1], context)
+    if len(ctmpl) == 1:
+        return ctmpl[0]  # fast path for string with no template fragment
+    return (runtemplate, ctmpl)
+
 def runtemplate(context, mapping, template):
     for func, data in template:
         yield func(context, mapping, data)
@@ -362,7 +370,7 @@
 
 def _evalifliteral(arg, context, mapping):
     # get back to token tag to reinterpret string as template
-    strtoken = {runstring: 'string', runrawstring: 'rawstring'}.get(arg[0])
+    strtoken = {runrawstring: 'rawstring'}.get(arg[0])
     if strtoken:
         yield runtemplate(context, mapping,
                           compiletemplate(arg[1], context, strtoken))
@@ -606,6 +614,7 @@
     "string": lambda e, c: (runstring, e[1]),
     "rawstring": lambda e, c: (runrawstring, e[1]),
     "symbol": lambda e, c: (runsymbol, e[1]),
+    "template": buildtemplate,
     "group": lambda e, c: compileexp(e[1], c, exprmethods),
 #    ".": buildmember,
     "|": buildfilter,
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
index a7dd6692e5cb197544578f0c6aa8629ee4debd99_dGVzdHMvdGVzdC1jb21tYW5kLXRlbXBsYXRlLnQ=..c1975809a6b5428478ae05326b31bca16bb6d537_dGVzdHMvdGVzdC1jb21tYW5kLXRlbXBsYXRlLnQ= 100644
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -2803,6 +2803,15 @@
   hg: parse error: expected a symbol, got 'integer'
   [255]
 
+Test string literal:
+
+  $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
+  string with no template fragment
+  $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
+  template: 0
+  $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
+  rawstring: {rev}
+
 Test string escaping:
 
   $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'