If you’ve ever hard-coded English labels in a Blogger theme and later wanted your interface to switch languages automatically, this guide is the missing piece. Blogger ships a powerful—but often overlooked—localization helper called data:messages. With it, you can surface standard UI strings like “By,” “Read more,” “Popular Posts,” and hundreds more in the visitor’s language without maintaining separate templates.
Below, we’ll unpack how data:messages works, the different ways to reference it (<data:…/>, <b:eval…/>, <b:message…/>), and how to safely output variations (HTML/JS/JSON/CSS-escaped) when you need to inject text into scripts or inline styles. We’ll also cover character length helpers, common pitfalls, and copy-paste snippets you can drop straight into your Blogger theme.
What is data:messages and why should you use it?
data:messages is a template-level dictionary of standard UI strings that Blogger provides. When your blog language is Indonesian, strings like By automatically become Oleh; switch to Spanish and they become De. That means fewer hard-coded labels, less duplication, and a clean path to multi-language support—especially helpful if you build or sell Blogger templates.
- Global scope: Available throughout the XML theme—widgets,
<b:includable>blocks, and more. - Auto-localized: Uses the blog’s language settings—no manual mapping files required.
- Multiple accessors: Output as plain text, or choose escaped variants for HTML/JS/JSON/CSS contexts.
- Stable keys: Keys like
data:messages.by,data:messages.readMore, etc., are consistent and documented through usage.
Result? Cleaner templates, less maintenance, and a better reader experience across locales.
Quick examples: three ways to print the same message
All three snippets below output the same localized value of data:messages.by (`By` / `Oleh` / `Par` / etc., depending on the blog language).
<!-- Direct message node -->
<data:messages.by/>
<!-- Evaluate the message expression -->
<b:eval expr='data:messages.by'/>
<!-- Message helper tag -->
<b:message name='messages.by'/>
Use whichever is most readable in your block. The output is identical, but you’ll prefer <b:eval…/> if you’re already concatenating in an expression.
Popular keys you’ll actually use
There are many keys. Here are common ones for navigation, bylines, and UI actions:
data:messages.by– By / Oleh / Pardata:messages.readMore– Read moredata:messages.popularPosts– Popular Postsdata:messages.latestPosts– Latest Postsdata:messages.keepReading– Keep readingdata:messages.search– Searchdata:messages.newer/older– Newer / Olderdata:messages.numberOfComments– {Count} commentsdata:messages.poweredByBlogger– Powered by Bloggerdata:messages.theresNothingHere– There’s nothing here!
Don’t forget: several keys accept substitutions or have link variations (e.g., author name with or without profile link). When you see examples like By <a href="...">Author</a>, that’s a linked variant of the base string.
Reference anatomy: string + helpers
Each message can expose helper fields for the same string—useful when embedding text inside attributes, scripts, JSON, or CSS:
"data": {
"messages": {
"by": message, {
"size": number,
"length": number,
"escaped": string,
"jsEscaped": string,
"jsonEscaped": string,
"cssEscaped": string
}
}
}
You won’t query JSON directly in your theme, but Blogger exposes these variants through its templating engine. Here is how you output them:
<!-- HTML ESCAPED (safe for markup) -->
<data:messages.by.escaped/>
<!-- JS ESCAPED (safe inside <script> strings) -->
<data:messages.by.jsEscaped/>
<!-- JSON ESCAPED (safe for JSON payloads) -->
<data:messages.by.jsonEscaped/>
<!-- CSS ESCAPED (safe in inline styles) -->
<data:messages.by.cssEscaped/>
When you only need plain text inside HTML content, the simple node <data:messages.by/> is fine. Reach for the escaped variants only when you’re injecting into:
- Inline JavaScript strings (
jsEscaped) - Inline JSON (e.g., data attributes) (
jsonEscaped) - Inline CSS content strings (
cssEscaped)
Character helpers: .size and .length
Sometimes you need to measure a string for layout reasons (e.g., truncation logic or conditional classes). Blogger exposes two helpers:
<!-- COUNT characters in the localized "By" message -->
<data:messages.by.size/>
<!-- Alternate length helper -->
<data:messages.by.length/>
For Indonesian (Oleh), both return 4. Use whichever you prefer; they serve the same purpose in typical themes.
Step-by-step: replacing hard-coded labels with data:messages
1) Byline (author) label
Many themes hard-code “By”. Replace it with the localized version:
<!-- Before -->
<span class='byline'>By <a expr:href='data:post.author.profileUrl'><data:post.author.name/></a></span>
<!-- After (auto-localized) -->
<span class='byline'>
<data:messages.by/>
<a expr:href='data:post.author.profileUrl'><data:post.author.name/></a>
</span>
2) “Read more” link
<!-- Before -->
<a class='read-more' expr:href='data:post.url'>Read more</a>
<!-- After -->
<a class='read-more' expr:href='data:post.url'><data:messages.readMore/></a>
3) Search placeholder
If your search field has a placeholder, localize it safely using escaped to guard the attribute:
<input class='search' type='search'
expr:placeholder='data:messages.search.escaped' />
4) Empty state (404 / nothing here)
<b:if cond='data:posts.length == 0'>
<p class='empty'><data:messages.theresNothingHere/></p>
</b:if>
5) Pagination labels (newer/older)
<nav class='pager'>
<b:if cond='data:newerPageUrl'>
<a class='newer' expr:href='data:newerPageUrl'><data:messages.newer/></a>
</b:if>
<b:if cond='data:olderPageUrl'>
<a class='older' expr:href='data:olderPageUrl'><data:messages.older/></a>
</b:if>
</nav>
Advanced: use escaped messages inside scripts and JSON
Inline JavaScript
When you must print a message inside a string literal, prefer jsEscaped so quotes/characters are safe:
<script>//<![CDATA[
var i18n = {
by: '<data:messages.by.jsEscaped/>',
readMore: '<data:messages.readMore.jsEscaped/>'
};
// Example: set button text dynamically
document.addEventListener('DOMContentLoaded', function(){
var btn = document.querySelector('.btn-readmore');
if(btn) btn.textContent = i18n.readMore;
});
//]]></script>
Inline JSON (e.g., data for a component)
<script type='application/json' id='i18n-json'>
{
"by": "<data:messages.by.jsonEscaped/>",
"search": "<data:messages.search.jsonEscaped/>"
}
</script>
Inline CSS content
Some designs add labels via content:. Use cssEscaped to avoid broken styles:
<style>
.badge-by::before {
content: "<data:messages.by.cssEscaped/>";
margin-right:.35rem;
opacity:.8;
}
</style>
Localization tips for template creators
- Prefer keys to literals: Every time you write a literal like “Share” ask, “Is there a
data:messageskey for this?” - Stay consistent: Don’t localize some labels and forget others—it feels off to readers.
- Use linked variants wisely: For author lines, try
byAuthorLinkwhen you need a profile anchor baked in. - Consider layout length: “Read more” is short in English, longer in other languages. Let your UI breathe.
- Polish the experience: If your theme uses long sidebars or drawers, keep visuals consistent. Many creators also customize scrollbar Blogger-style with a Blogger CSS scrollbar snippet so the interface feels cohesive (see the custom scrollbar tutorial linked above).
Troubleshooting
- “Nothing prints” where I used a key: Check spelling and case. Keys are precise:
data:messages.readMore≠data:messages.readmore. - HTML breaks when echoing inside attributes: Use the right escaped variant (
escapedfor HTML attributes,jsEscapedfor scripts,jsonEscapedfor JSON,cssEscapedfor CSS). - Mixed languages across the page: Verify the blog’s language is set correctly in Settings → Language. Some widgets may also include their own hard-coded text—swap those for
data:messagesequivalents. - My custom key doesn’t resolve:
data:messagescovers built-in Blogger strings. For entirely custom phrases, create your own logic (e.g., condition ondata:blog.locale) or keep literals minimal and neutral. - Special characters look odd in CSS
content:: UsecssEscaped, not the raw message node. - Need different text case: If your design requires uppercase, use CSS
text-transform: uppercase;instead of altering the message.
FAQ
1) Can I use data:messages inside posts or pages?
No—these helpers are for the template (theme) layer. Use them in widgets, headers, footers, and post templates, not inside the content editor.
2) How do I show language-specific blocks when I don’t find a message key?
Leverage the blog locale switch:
<b:switch var='data:blog.locale'>
<b:case value='id' />Teks Indonesia
<b:case value='es' />Texto en español
<b:default />English text
</b:switch>
3) Are there keys for comments, archives, and “Powered by Blogger”?
Yes—among others: comments, blogArchive, poweredByBlogger, poweredByBloggerLink. Replace literals anywhere they appear.
4) What’s the difference between size and length?
In practice, for these message nodes, they function the same in templates. Use either when you need a character count for layout logic.
5) Does using data:messages help SEO?
Indirectly. It improves UX, reduces bounce (clearer labels), and signals a well-structured UI. For multilingual blogs, it makes your template feel native in each locale—always a plus.
6) Can I combine data:messages with custom JavaScript components?
Definitely. Build a small window.i18n object by printing jsEscaped or jsonEscaped values and feed those into your components at runtime.
Copy-Paste Cookbook
Print a linked author line, localized
<span class='byline'>
<data:messages.by/>
<a expr:href='data:post.author.profileUrl'><data:post.author.name/></a>
</span>
Localize “Popular Posts” widget title
<div class='widget-title'>
<h3><span><data:messages.popularPosts/></span></h3>
</div>
Safety in attributes with escaped
<a class='cta' expr:aria-label='data:messages.readMore.escaped' expr:title='data:messages.readMore.escaped'>
<data:messages.readMore/>
</a>
Inline JSON bundle for a widget
<script type='application/json' id='ui-i18n'>
{
"newer": "<data:messages.newer.jsonEscaped/>",
"older": "<data:messages.older.jsonEscaped/>",
"keepReading": "<data:messages.keepReading.jsonEscaped/>"
}
</script>
Design notes to keep your UI tidy
- Whitespace: When concatenating message + dynamic value (e.g., “By” + author), remember spacing (
or CSS margins). - Responsiveness: Some languages expand strings more than English; set flexible widths and avoid cramped labels.
- Consistency: If you localize your nav and headings, also localize button labels, pagination, and microcopy (search, share, subscribe).
- Scrollbar styling: For long widget panels, a matching Blogger CSS scrollbar (from a custom scrollbar tutorial) keeps your template visually consistent.
Conclusion
data:messages is one of those quiet features that separates a quick theme hack from a professional, multilingual Blogger template. Replace hard-coded text with message keys, use escaped variants when the context demands, and give your readers a UI that speaks their language—literally.
If this was helpful, you might enjoy our other UI polish pieces—from dark mode toggles to how to customize scrollbar Blogger-style for a cleaner reading flow.
Enjoyed the guide? Bookmark it for later, share it with a fellow creator, and subscribe so you don’t miss the next hands-on tutorial.



Post a Comment
Please keep your comments relevant to the topic discussed in the article.
Be respectful — no spam, offensive language, or personal attacks.
You may share suggestions, feedback, or questions related to the content.
External links are allowed only if they are truly helpful and not for self-promotion.
All comments may be reviewed before appearing on the site.
By commenting here, you help keep the discussion useful and improve the KodeRian community.