You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在JavaScript模板字面量中通过Handlebars JS调用语言包键

如何在JavaScript模板字面量中通过Handlebars JS调用语言包键

我明白你的问题了——你在JavaScript模板字面量里写了Handlebars的{{ lang ... }}表达式,但页面渲染后这些表达式直接变成了纯文本,没有替换成语言包里的实际文字。这其实是因为Handlebars的模板渲染时机和你的JavaScript执行时机不匹配

Handlebars通常是在服务器端或者页面加载初期预编译/渲染模板的,而你是在浏览器运行时通过JavaScript动态生成HTML,这时候Handlebars已经完成了它的工作,自然不会再解析你后来插入的{{ lang }}表达式了。

下面给你几个可行的解决方案,你可以根据自己的项目情况选择:


方案1:直接引用客户端可用的语言包变量

如果你的项目已经把语言包数据暴露成了全局变量(比如很多电商平台会把多语言内容挂在window.lang或者类似的全局对象上),那你完全可以跳过Handlebars表达式,直接在JavaScript里引用这些变量:

比如假设全局语言对象是window.lang,那你可以把模板里的{{ lang "products.quick_view" }}换成${lang.products.quick_view},修改后的代码片段如下:

productElement.innerHTML += `
    <article class="card" data-event-type="list" data-name="${result.name}" data-product-category="" data-product-brand="${result.brand}" data-product-price="${result.price}">
        <!-- 省略其他代码 -->
        <button type="button" class="button button--small card-figcaption-button quickview" data-event-type="product-click">${lang.products.quick_view}</button>
        <label class="button button--small card-figcaption-button">
            ${lang.products.compare}
            <input type="checkbox" name="products[]">
        </label>
        <a href="${result.url}" data-event-type="product-click" class="button button--small card-figcaption-button">${lang.products.choose_options}</a>
        <!-- 省略其他代码 -->
    </article>
`;

这种方法最简单直接,只要确认语言包变量在客户端是可访问的就行。


方案2:提前把语言字符串渲染到页面的隐藏元素中

如果语言包没有全局暴露,但你可以在页面初始渲染时通过Handlebars把需要的字符串存起来,那可以用HTML的data-*属性来存储这些值,然后在JavaScript里读取:

首先在你的HTML里添加一个隐藏的容器,用Handlebars渲染出需要的语言字符串:

<!-- 放在页面任意位置,比如脚本上方 -->
<div id="lang-cache" style="display: none;"
     data-quick-view="{{ lang 'products.quick_view' }}"
     data-compare="{{ lang 'products.compare' }}"
     data-choose-options="{{ lang 'products.choose_options' }}">
</div>

然后在你的JavaScript里先获取这些值:

// 在displayResults函数外或者函数开头获取
const langCache = document.getElementById('lang-cache');
const quickViewText = langCache.dataset.quickView;
const compareText = langCache.dataset.compare;
const chooseOptionsText = langCache.dataset.chooseOptions;

之后在模板字面量里用这些变量替换原来的Handlebars表达式:

productElement.innerHTML += `
    <!-- 省略其他代码 -->
    <button type="button" class="button button--small card-figcaption-button quickview" data-event-type="product-click">${quickViewText}</button>
    <label class="button button--small card-figcaption-button">
        ${compareText}
        <input type="checkbox" name="products[]">
    </label>
    <a href="${result.url}" data-event-type="product-click" class="button button--small card-figcaption-button">${chooseOptionsText}</a>
    <!-- 省略其他代码 -->
`;

这种方法适合语言包没有全局暴露,但你能控制页面初始HTML的场景。


方案3:使用客户端Handlebars编译动态模板

如果你的项目已经引入了客户端版的Handlebars库,那可以把产品卡片写成一个Handlebars模板,然后在JavaScript里编译并渲染:

首先在HTML里定义Handlebars模板:

<script id="product-card-template" type="text/x-handlebars-template">
    <article class="card" data-event-type="list" data-name="{{name}}" data-product-category="" data-product-brand="{{brand}}" data-product-price="{{price}}">
        <figure class="card-figure">
            <a href="{{url}}" class="card-figure__link" target="_blank" aria-label="{{name}}, {{price}}" data-event-type="product-click">
                <div class="card-img-container">
                    <img src="{{img}}" class="card-image lazyautosizes ls-is-cached lazyloaded" alt="{{name}}" title="{{name}}" data-sizes="auto" srcset="{{img}}" data-srcset="{{img}}" sizes="285px">
                </div>
            </a>
            <figcaption class="card-figcaption">
                <div class="card-figcaption-body">
                    <button type="button" class="button button--small card-figcaption-button quickview" data-event-type="product-click">{{lang "products.quick_view"}}</button>
                    <label class="button button--small card-figcaption-button">
                        {{lang "products.compare"}}
                        <input type="checkbox" name="products[]">
                    </label>
                    <a href="{{url}}" data-event-type="product-click" class="button button--small card-figcaption-button">{{lang "products.choose_options"}}</a>
                </div>
            </figcaption>
        </figure>
        <div class="card-body">
            <p class="card-text" data-test-info-type="brandName">{{brand}}</p>
            <h3 class="card-title">
                <a href="{{url}}" target="_blank">{{name}}</a>
            </h3>
            <div class="card-text" data-test-info-type="price">
                <div class="price-section price-section--withoutTax">
                    <span class="price-label"></span>
                    <span class="price-now-label" style="display: none;"></span>
                    <span data-product-price-without-tax class="price price--withoutTax">${{price}}</span>
                </div>
            </div>
        </div>
    </article>
</script>

然后在JavaScript里编译这个模板,并渲染每个产品:

// 先编译模板(可以放在页面加载完成后)
const productTemplate = Handlebars.compile(document.getElementById('product-card-template').innerHTML);

// 确保Handlebars能识别lang helper(如果项目没自动注册的话)
Handlebars.registerHelper('lang', function(key) {
    // 这里替换成你实际获取语言字符串的逻辑,比如从全局变量取
    return window.lang[key] || key;
});

function displayResults() {
    questionContainer.textContent = "Your recommended product(s):";
    optionsContainer.innerHTML = "";
    
    if (filteredProducts.length > 0) {
        filteredProducts.forEach(result => {
            const productElement = document.createElement("li");
            productElement.classList.add("product");
            // 用模板渲染产品数据
            productElement.innerHTML = productTemplate(result);
            optionsContainer.appendChild(productElement);
        });
    } else {
      optionsContainer.textContent = "No products match your criteria. Please try again!";
    }

    // 省略重启按钮代码...
}

这种方法更符合Handlebars的使用规范,但需要确保客户端能访问Handlebars库和lang helper。


备注:内容来源于stack exchange,提问作者Deo3560

火山引擎 最新活动