b2c-isml
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseISML Skill
ISML 使用指南
This skill guides you through creating and working with ISML (Isomorphic Markup Language) templates in Salesforce B2C Commerce. ISML templates combine HTML with dynamic server-side tags.
本指南将指导你在Salesforce B2C Commerce中创建和使用ISML(同构标记语言)模板。ISML模板将HTML与动态服务器端标签相结合。
Overview
概述
ISML templates are server-side templates that generate HTML. They use special tags prefixed with and expressions in syntax to embed dynamic content.
is${...}ISML模板是用于生成HTML的服务器端模板。它们使用以为前缀的特殊标签和语法的表达式来嵌入动态内容。
is${...}File Location
文件位置
Templates reside in the cartridge's directory:
templates/my-cartridge
/cartridge
/templates
/default # Default locale
/product
detail.isml
tile.isml
/home
homepage.isml
/util
modules.isml # Custom tag definitions
/fr_FR # French-specific templates
/product
detail.isml模板存放在 cartridge 的目录中:
templates/my-cartridge
/cartridge
/templates
/default # 默认语言区域
/product
detail.isml
tile.isml
/home
homepage.isml
/util
modules.isml # 自定义标签定义
/fr_FR # 法语专属模板
/product
detail.ismlEssential Tags
核心标签
Conditional Logic
条件逻辑
html
<isif condition="${product.available}">
<span class="in-stock">In Stock</span>
<iselseif condition="${product.preorderable}">
<span class="preorder">Pre-order</span>
<iselse>
<span class="out-of-stock">Out of Stock</span>
</isif>html
<isif condition="${product.available}">
<span class="in-stock">有货</span>
<iselseif condition="${product.preorderable}">
<span class="preorder">可预订</span>
<iselse>
<span class="out-of-stock">缺货</span>
</isif>Loops
循环
html
<isloop items="${products}" var="product" status="loopstate">
<div class="product ${loopstate.odd ? 'odd' : 'even'}">
<span>${loopstate.count}. ${product.name}</span>
<isif condition="${loopstate.first}">
<span class="badge">Featured</span>
</isif>
</div>
</isloop>Loop status properties:
- - Iteration number (1-based)
count - - Current index (0-based)
index - - Boolean, true on first iteration
first - - Boolean, true on last iteration
last - - Boolean, true on odd iterations
odd - - Boolean, true on even iterations
even
html
<isloop items="${products}" var="product" status="loopstate">
<div class="product ${loopstate.odd ? 'odd' : 'even'}">
<span>${loopstate.count}. ${product.name}</span>
<isif condition="${loopstate.first}">
<span class="badge">精选</span>
</isif>
</div>
</isloop>循环状态属性:
- - 迭代次数(从1开始)
count - - 当前索引(从0开始)
index - - 布尔值,首次迭代时为true
first - - 布尔值,最后一次迭代时为true
last - - 布尔值,奇数次迭代时为true
odd - - 布尔值,偶数次迭代时为true
even
Variables
变量
html
<!-- Set a variable (scope is required) -->
<isset name="productName" value="${product.name}" scope="page"/>
<!-- Use the variable -->
<span>${productName}</span>
<!-- Remove a variable -->
<isremove name="productName" scope="page"/>Scopes (required): , , ,
pagerequestsessionpdicthtml
<!-- 设置变量(必须指定作用域) -->
<isset name="productName" value="${product.name}" scope="page"/>
<!-- 使用变量 -->
<span>${productName}</span>
<!-- 移除变量 -->
<isremove name="productName" scope="page"/>作用域(必填): , , ,
pagerequestsessionpdictOutput
输出
html
<!-- Basic output (HTML encoded by default) -->
<isprint value="${product.name}"/>
<!-- Unencoded output (use carefully) -->
<isprint value="${htmlContent}" encoding="off"/>
<!-- Formatted number -->
<isprint value="${price}" style="CURRENCY"/>
<!-- Formatted date -->
<isprint value="${order.creationDate}" style="DATE_SHORT"/>html
<!-- 基础输出(默认自动HTML编码) -->
<isprint value="${product.name}"/>
<!-- 未编码输出(谨慎使用) -->
<isprint value="${htmlContent}" encoding="off"/>
<!-- 格式化数字 -->
<isprint value="${price}" style="CURRENCY"/>
<!-- 格式化日期 -->
<isprint value="${order.creationDate}" style="DATE_SHORT"/>Include Templates
引用模板
html
<!-- Include local template -->
<isinclude template="product/components/price"/>
<!-- Include with URL (remote include) -->
<isinclude url="${URLUtils.url('Product-GetPrice', 'pid', product.ID)}"/>html
<!-- 引用本地模板 -->
<isinclude template="product/components/price"/>
<!-- 通过URL引用(远程引用) -->
<isinclude url="${URLUtils.url('Product-GetPrice', 'pid', product.ID)}"/>Decorator Pattern
装饰器模式
Base decorator (layouts/pagelayout.isml):
html
<!DOCTYPE html>
<html>
<head>
<title>${pdict.pageTitle}</title>
</head>
<body>
<header>
<isinclude template="components/header"/>
</header>
<main>
<isreplace/> <!-- Content inserted here -->
</main>
<footer>
<isinclude template="components/footer"/>
</footer>
</body>
</html>Page using decorator:
html
<isdecorate template="layouts/pagelayout">
<isslot id="home-banner" context="global"/>
<div class="homepage-content">
<h1>${pdict.welcomeMessage}</h1>
</div>
</isdecorate>基础装饰器(layouts/pagelayout.isml):
html
<!DOCTYPE html>
<html>
<head>
<title>${pdict.pageTitle}</title>
</head>
<body>
<header>
<isinclude template="components/header"/>
</header>
<main>
<isreplace/> <!-- 内容将插入此处 -->
</main>
<footer>
<isinclude template="components/footer"/>
</footer>
</body>
</html>使用装饰器的页面:
html
<isdecorate template="layouts/pagelayout">
<isslot id="home-banner" context="global"/>
<div class="homepage-content">
<h1>${pdict.welcomeMessage}</h1>
</div>
</isdecorate>Expressions
表达式
Expressions use syntax to embed dynamic values:
${...}html
<!-- Property access -->
${product.name}
${product.price.sales.value}
<!-- Method calls -->
${product.getAvailabilityModel().isInStock()}
<!-- Built-in objects -->
${pdict.myVariable} <!-- Controller data -->
${session.customer.firstName} <!-- Session data -->
${request.httpParameterMap.pid.stringValue}
<!-- Operators -->
${price > 100 ? 'expensive' : 'affordable'}
${firstName + ' ' + lastName}
${quantity * unitPrice}表达式使用语法嵌入动态值:
${...}html
<!-- 属性访问 -->
${product.name}
${product.price.sales.value}
<!-- 方法调用 -->
${product.getAvailabilityModel().isInStock()}
<!-- 内置对象 -->
${pdict.myVariable} <!-- 控制器数据 -->
${session.customer.firstName} <!-- 会话数据 -->
${request.httpParameterMap.pid.stringValue}
<!-- 运算符 -->
${price > 100 ? '高价' : '平价'}
${firstName + ' ' + lastName}
${quantity * unitPrice}Built-in Utilities
内置工具
URLUtils
URLUtils
html
<!-- Controller URL -->
<a href="${URLUtils.url('Product-Show', 'pid', product.ID)}">View</a>
<!-- HTTPS URL -->
<a href="${URLUtils.https('Account-Show')}">My Account</a>
<!-- Static resource -->
<img src="${URLUtils.staticURL('/images/logo.png')}" alt="Logo"/>
<!-- Absolute URL -->
<a href="${URLUtils.abs('Home-Show')}">Home</a>html
<!-- 控制器URL -->
<a href="${URLUtils.url('Product-Show', 'pid', product.ID)}">查看详情</a>
<!-- HTTPS URL -->
<a href="${URLUtils.https('Account-Show')}">我的账户</a>
<!-- 静态资源 -->
<img src="${URLUtils.staticURL('/images/logo.png')}" alt="Logo"/>
<!-- 绝对URL -->
<a href="${URLUtils.abs('Home-Show')}">首页</a>Resource (Localization)
Resource(本地化)
html
<!-- Get localized string -->
${Resource.msg('button.addtocart', 'product', null)}
<!-- With parameters -->
${Resource.msgf('cart.items', 'cart', null, cartCount)}html
<!-- 获取本地化字符串 -->
${Resource.msg('button.addtocart', 'product', null)}
<!-- 带参数 -->
${Resource.msgf('cart.items', 'cart', null, cartCount)}StringUtils
StringUtils
html
<!-- Truncate text -->
${StringUtils.truncate(description, 100, '...')}
<!-- Format number -->
${StringUtils.formatNumber(quantity, '###,###')}html
<!-- 截断文本 -->
${StringUtils.truncate(description, 100, '...')}
<!-- 格式化数字 -->
${StringUtils.formatNumber(quantity, '###,###')}Custom Modules
自定义模块
Define reusable custom tags in :
util/modules.ismlhtml
<!-- Definition in util/modules.isml -->
<ismodule template="components/productcard"
name="productcard"
attribute="product"
attribute="showPrice"
attribute="showRating"/>
<!-- Usage in any template -->
<isinclude template="util/modules"/>
<isproductcard product="${product}" showPrice="${true}" showRating="${true}"/>Component template (components/productcard.isml):
html
<div class="product-card">
<img src="${product.image.url}" alt="${product.name}"/>
<h3>${product.name}</h3>
<isif condition="${pdict.showPrice}">
<span class="price">${product.price.sales.formatted}</span>
</isif>
<isif condition="${pdict.showRating && product.rating}">
<span class="rating">${product.rating} stars</span>
</isif>
</div>在中定义可复用的自定义标签:
util/modules.ismlhtml
<!-- 在util/modules.isml中定义 -->
<ismodule template="components/productcard"
name="productcard"
attribute="product"
attribute="showPrice"
attribute="showRating"/>
<!-- 在任意模板中使用 -->
<isinclude template="util/modules"/>
<isproductcard product="${product}" showPrice="${true}" showRating="${true}"/>组件模板(components/productcard.isml):
html
<div class="product-card">
<img src="${product.image.url}" alt="${product.name}"/>
<h3>${product.name}</h3>
<isif condition="${pdict.showPrice}">
<span class="price">${product.price.sales.formatted}</span>
</isif>
<isif condition="${pdict.showRating && product.rating}">
<span class="rating">${product.rating} 星</span>
</isif>
</div>Caching
缓存
html
<!-- Cache for 24 hours -->
<iscache type="relative" hour="24"/>
<!-- Daily cache (expires at midnight) -->
<iscache type="daily" hour="0" minute="0"/>
<!-- Vary cache by parameter -->
<iscache type="relative" hour="1" varyby="price_promotion"/>Place at the beginning of the template.
<iscache>html
<!-- 缓存24小时 -->
<iscache type="relative" hour="24"/>
<!-- 每日缓存(午夜过期) -->
<iscache type="daily" hour="0" minute="0"/>
<!-- 根据参数区分缓存 -->
<iscache type="relative" hour="1" varyby="price_promotion"/>将放在模板开头。
<iscache>Content Type
内容类型
html
<!-- Set content type (must be first in template) -->
<iscontent type="text/html" charset="UTF-8"/>
<!-- For JSON responses -->
<iscontent type="application/json" charset="UTF-8"/>
<!-- For XML -->
<iscontent type="application/xml" charset="UTF-8"/>html
<!-- 设置内容类型(必须在模板最开头) -->
<iscontent type="text/html" charset="UTF-8"/>
<!-- 用于JSON响应 -->
<iscontent type="application/json" charset="UTF-8"/>
<!-- 用于XML -->
<iscontent type="application/xml" charset="UTF-8"/>Embedded Scripts
嵌入式脚本
html
<isscript>
var ProductMgr = require('dw/catalog/ProductMgr');
var product = ProductMgr.getProduct(pdict.pid);
var price = product.priceModel.price;
</isscript>
<span>${price.toFormattedString()}</span>Best Practice: Keep blocks minimal. Move complex logic to controllers or helper scripts.
<isscript>html
<isscript>
var ProductMgr = require('dw/catalog/ProductMgr');
var product = ProductMgr.getProduct(pdict.pid);
var price = product.priceModel.price;
</isscript>
<span>${price.toFormattedString()}</span>最佳实践: 尽量减少代码块的内容。将复杂逻辑移至控制器或辅助脚本中。
<isscript>Comments
注释
html
<!-- HTML comment (visible in source) -->
<iscomment>
ISML comment - stripped from output.
Use for documentation and hiding sensitive info.
</iscomment>html
<!-- HTML注释(在源码中可见) -->
<iscomment>
ISML注释 - 会从输出中移除。
用于文档编写和隐藏敏感信息。
</iscomment>Tag Location Constraints
标签位置限制
Not all ISML tags can be used anywhere. Important constraints:
| Tag | Allowed Location |
|---|---|
| Must be before DOCTYPE declaration |
| Must be before DOCTYPE declaration |
| Only in |
| Only in |
| Only in |
| Inside |
| Must be within |
| Only in |
Tags that can be used anywhere: , , , , , , , , , .
<isif><isloop><isinclude><isset><isremove><iscache><iscomment><ismodule><iscookie><isstatus>并非所有ISML标签都可以在任意位置使用。重要限制如下:
| 标签 | 允许位置 |
|---|---|
| 必须在DOCTYPE声明之前 |
| 必须在DOCTYPE声明之前 |
| 仅可在 |
| 仅可在 |
| 仅可在 |
| 位于 |
| 必须在 |
| 仅可在 |
可在任意位置使用的标签:, , , , , , , , , 。
<isif><isloop><isinclude><isset><isremove><iscache><iscomment><ismodule><iscookie><isstatus>Best Practices
最佳实践
- Use instead of HTML comments for sensitive info
<iscomment> - Place first in templates that need it
<iscontent> - Define modules in for consistency
util/modules.isml - Keep templates simple - move logic to controllers/helpers
- Use decorators for consistent page layouts
- Enable caching on cacheable pages with
<iscache> - Encode output - default encoding prevents XSS
- 使用替代HTML注释来隐藏敏感信息
<iscomment> - 将放在最开头 在需要设置内容类型的模板中
<iscontent> - 在中定义模块 以保持一致性
util/modules.isml - 保持模板简洁 - 将逻辑移至控制器/辅助脚本
- 使用装饰器 实现一致的页面布局
- 为可缓存页面启用缓存 使用标签
<iscache> - 对输出进行编码 - 默认编码可防止XSS攻击
Detailed Reference
详细参考
For comprehensive tag documentation:
- Tags Reference - All ISML tags with examples
- Expressions Reference - Expression syntax and built-in functions
如需完整的标签文档:
- 标签参考 - 所有ISML标签及示例
- 表达式参考 - 表达式语法和内置函数