<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Localization Helper in 3.3.0]]></title><description><![CDATA[<p>Hi,</p>
<p>Our template structure looks like this<br />
<img src="/uploads/files/1642670143371-upload-62b01d74-67bd-49cb-80b6-3f3150d45b42.png" alt="0_1642670143335_upload-62b01d74-67bd-49cb-80b6-3f3150d45b42" class="img-responsive img-markdown" /></p>
<p>Besides other functions we have a <code>translate</code> function in our <code>global-helper.js</code> since all our localization is located in a sub-folder <em>translation</em>, it''s quite handy in a report templates to write <code>{{translate &quot;text&quot;}}</code>.</p>
<pre><code class="language-js">const jsreport = require('jsreport-proxy');

function translate(key) {
    return jsreport.localization.localize(key, &quot;translations&quot;);
}
</code></pre>
<p>Since the upgrade to jsreport 3.3.0 we face the following error message with our setup.</p>
<pre><code class="language-js">Report &quot;reportB&quot; render failed.

Error when evaluating engine handlebars for template /reportB/reportB
localize helper couldn't find asset with data at translations/en.json
Error: localize helper couldn't find asset with data at translations/en.json
    at Object.localize (/app/node_modules/@jsreport/jsreport-localization/lib/worker.js:44:17)
    at async /app/node_modules/@jsreport/jsreport-core/lib/worker/render/executeEngine.js:133:40
    at async Promise.all (index 0)
    at async executionFn (/app/node_modules/@jsreport/jsreport-core/lib/worker/render/executeEngine.js:132:9)
</code></pre>
<p>Are we doing something wrong? Was this changed from 3.2.0 to 3.3.0 and if so, is there a possibility to fix this? Is there another way to solve the situation?</p>
<p>The release notes of 3.3.0 state <em>&quot;fix not resolving relative path correctly when calling asset code from another asset&quot;</em>. Is this maybe the reason?</p>
<p>You can find a <a href="https://playground.jsreport.net/w/ThomasJReiter/V7WHR8x5" rel="nofollow">setup here</a></p>
<p>Thanks in advance for any advice.</p>
]]></description><link>https://forum.jsreport.net/topic/2276/localization-helper-in-3-3-0</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Jul 2026 04:47:35 GMT</lastBuildDate><atom:link href="https://forum.jsreport.net/topic/2276.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 20 Jan 2022 09:39:05 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Thu, 20 Jan 2022 09:43:19 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>Our template structure looks like this<br />
<img src="/uploads/files/1642670143371-upload-62b01d74-67bd-49cb-80b6-3f3150d45b42.png" alt="0_1642670143335_upload-62b01d74-67bd-49cb-80b6-3f3150d45b42" class="img-responsive img-markdown" /></p>
<p>Besides other functions we have a <code>translate</code> function in our <code>global-helper.js</code> since all our localization is located in a sub-folder <em>translation</em>, it''s quite handy in a report templates to write <code>{{translate &quot;text&quot;}}</code>.</p>
<pre><code class="language-js">const jsreport = require('jsreport-proxy');

function translate(key) {
    return jsreport.localization.localize(key, &quot;translations&quot;);
}
</code></pre>
<p>Since the upgrade to jsreport 3.3.0 we face the following error message with our setup.</p>
<pre><code class="language-js">Report &quot;reportB&quot; render failed.

Error when evaluating engine handlebars for template /reportB/reportB
localize helper couldn't find asset with data at translations/en.json
Error: localize helper couldn't find asset with data at translations/en.json
    at Object.localize (/app/node_modules/@jsreport/jsreport-localization/lib/worker.js:44:17)
    at async /app/node_modules/@jsreport/jsreport-core/lib/worker/render/executeEngine.js:133:40
    at async Promise.all (index 0)
    at async executionFn (/app/node_modules/@jsreport/jsreport-core/lib/worker/render/executeEngine.js:132:9)
</code></pre>
<p>Are we doing something wrong? Was this changed from 3.2.0 to 3.3.0 and if so, is there a possibility to fix this? Is there another way to solve the situation?</p>
<p>The release notes of 3.3.0 state <em>&quot;fix not resolving relative path correctly when calling asset code from another asset&quot;</em>. Is this maybe the reason?</p>
<p>You can find a <a href="https://playground.jsreport.net/w/ThomasJReiter/V7WHR8x5" rel="nofollow">setup here</a></p>
<p>Thanks in advance for any advice.</p>
]]></description><link>https://forum.jsreport.net/post/9939</link><guid isPermaLink="true">https://forum.jsreport.net/post/9939</guid><dc:creator><![CDATA[ThomasJReiter]]></dc:creator><pubDate>Thu, 20 Jan 2022 09:43:19 GMT</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Thu, 20 Jan 2022 10:30:35 GMT]]></title><description><![CDATA[<p>Yes, this was changed in 3.3.0 because we considered it as a bug. Now everything is resolved relative to the particular entity. We consider it as a better approach.</p>
<p>The following approach could work for you</p>
<pre><code>const jsreport = require('jsreport-proxy');

async function translate(key) {
    const template = jsreport.req.template
    const templatePath = await jsreport.folders.resolveEntityPath(template, 'templates')
    const folderPath = templatePath.substring(0, templatePath.lastIndexOf('/'))
    return jsreport.localization.localize(key, folderPath + '/translations');
}
</code></pre>
<p><a href="https://playground.jsreport.net/w/anon/K78DqxIW" rel="nofollow">https://playground.jsreport.net/w/anon/K78DqxIW</a></p>
<p>We are considering some improvements for the future versions:</p>
<ul>
<li>default to &quot;translations&quot; folder in localize function so the second argument won't be needed</li>
<li>a one-liner function to resolve the current template path or folder</li>
</ul>
<p>Thank you for the demo and the great description!</p>
]]></description><link>https://forum.jsreport.net/post/9941</link><guid isPermaLink="true">https://forum.jsreport.net/post/9941</guid><dc:creator><![CDATA[jan_blaha]]></dc:creator><pubDate>Thu, 20 Jan 2022 10:30:35 GMT</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Thu, 20 Jan 2022 12:49:40 GMT]]></title><description><![CDATA[<p>Thanks for the fast response, works well.</p>
<p>Just out of curiosity, are you considering a fallback to a default localization if no language is found? Currently an exception is thrown and the whole report won't build.</p>
<p>Edit: I added our fallback handling in the playground example from above.</p>
]]></description><link>https://forum.jsreport.net/post/9942</link><guid isPermaLink="true">https://forum.jsreport.net/post/9942</guid><dc:creator><![CDATA[ThomasJReiter]]></dc:creator><pubDate>Thu, 20 Jan 2022 12:49:40 GMT</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Invalid Date]]></title><description><![CDATA[<p>The default language can be set on the template itself. See in the studio template properties -&gt; localization -&gt; Template language</p>
<p>Another option is to use a custom script, which can be scoped globaly or also to a particular folder.<br />
<a href="https://jsreport.net/learn/scripts#script-scope" rel="nofollow">https://jsreport.net/learn/scripts#script-scope</a></p>
<pre><code>async function beforeRender (req, res) {
    req.options.localization = req.options.localization  || { language: 'en' }
}
</code></pre>
]]></description><link>https://forum.jsreport.net/post/9948</link><guid isPermaLink="true">https://forum.jsreport.net/post/9948</guid><dc:creator><![CDATA[jan_blaha]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Invalid Date]]></title><description><![CDATA[<p>Thanks for the clarification.</p>
<p>What I meant was that we fallback for each translation individually. If not found in the given language we search in english and if we don't find it there we return the <em>[key]</em> instead of <em>undefined</em>. Outlined in reportB of the example.<br />
<a href="https://playground.jsreport.net/w/anon/K78DqxIW" rel="nofollow">https://playground.jsreport.net/w/anon/K78DqxIW</a></p>
]]></description><link>https://forum.jsreport.net/post/9949</link><guid isPermaLink="true">https://forum.jsreport.net/post/9949</guid><dc:creator><![CDATA[ThomasJReiter]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Invalid Date]]></title><description><![CDATA[<p>I see, thank you for the suggestion. It seems to me that the requirements can differ and not yet sure which approach should be provided from us by design. I think we would start by documenting how you can adapt the localization function and see in time what is the most common usage.</p>
<p>The current localization is missing explicit language specification. We will add it in the next release.<br />
Then a complex use case like yours can be implemented like this.</p>
<pre><code class="language-js">const jsreport = require('jsreport-proxy');
const defaultLanguage = 'cz'

// add to helpers custom localization function
async function translate(key, translationsPath) {   
    if (typeof translationsPath !== 'string') {
        // default to specific translations folder
        const template = jsreport.req.template
        const templatePath = await jsreport.folders.resolveEntityPath(template, 'templates')
        const folderPath = templatePath.substring(0, templatePath.lastIndexOf('/'))
        translationsPath = folderPath + '/translations'
    }

    let localizedVal
    try {
        localizedVal = await jsreport.localization.localize(key, translationsPath)
    } catch (e) {
         // asset with requested language not found, try default language
         try {
            localizedVal = await jsreport.localization.localize({
                key, 
                folder: translationsPath,
                language: defaultLanguage
            })
         } catch (e) {
             // asset for default language not found
             return `[${key}]`
         }
    }

    if (localizedVal == null) {
        // key not found in the asset, try search for key in the asset for default language
        try {
            localizedVal = await jsreport.localization.localize({
                key, 
                folder: translationsPath,
                language: defaultLanguage
            })
        } catch (e) {
            // asset for default language not found
            return `[${key}]`
        }
        if (localizedVal == null) {
            return `[${key}]`
        }
        return localizedVal
    }

    return localizedVal
}
</code></pre>
<p>Do you have some thoughts/comments on what we plan?</p>
]]></description><link>https://forum.jsreport.net/post/9958</link><guid isPermaLink="true">https://forum.jsreport.net/post/9958</guid><dc:creator><![CDATA[jan_blaha]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[Reply to Localization Helper in 3.3.0 on Invalid Date]]></title><description><![CDATA[<p>For me it would be fine to stay with your current implementation and document the use-case somewhere in a how-to.</p>
<p>Currently our complex case is implemented like this.</p>
<pre><code>async function translateWithFallback(key) {
    const template = jsreport.req.template
    const templatePath = await jsreport.folders.resolveEntityPath(template, 'templates')
    const folderPath = templatePath.substring(0, templatePath.lastIndexOf('/'))

    return jsreport.localization.localize(key, folderPath + '/translations')
        .then(translation =&gt; {
            return !translation ? fallbackTranslation(key) : translation
        })
        .catch((e) =&gt; fallbackTranslation(key));
}

function fallbackTranslation(key) {
    const defaultDataPath = &quot;translations/en.json&quot;;
    return jsreport.folders.resolveEntityFromPath(defaultDataPath, 'assets')
        .then(function(resolvedValue) {
            return JSON.parse(resolvedValue.entity.content.toString());
        })
        .then(function(data) {
            var v = data[key]
            return !v ?  &quot;[&quot; + key + &quot;]&quot; : &quot;*&quot; + v;
        })
}
</code></pre>
<p>Of course neither capable of special translation folders nor any other fallback language then English.</p>
]]></description><link>https://forum.jsreport.net/post/9960</link><guid isPermaLink="true">https://forum.jsreport.net/post/9960</guid><dc:creator><![CDATA[ThomasJReiter]]></dc:creator><pubDate>Invalid Date</pubDate></item></channel></rss>