Giter VIP home page Giter VIP logo

makara's Introduction

Makara

Build Status

A module to set up internationalization in Kraken and Express.js apps.

makara is the more opinionated configuration of its component parts, suitable for dropping into an express application and working with relatively little configuration.

It consists of bundalo for loading localized strings for use by application logic, engine-munger for controlling the lookup of templates and associated localized strings, and includes adaro as a template engine, connecting dustjs-linkedin to Express.

There's nothing inherently dust-centric about makara, but it does provide dust template engines as a default.

Using Makara

Here's a tiny but complete application

var express = require('express');
var makara = require('makara');
var path = require('path');

var app = express();

var helpers = [ 'dust-makara-helpers' ];
var env = process.env.NODE_ENV;
app.engine('dust', makara.dust({ cache: false, helpers: helpers }));
app.engine('js', makara.js({ cache: true, helpers: helpers }));

app.set('views', path.resolve(__dirname, 'public/templates'));

if (env === 'development') {
    app.set('view engine', 'dust');
} else {
    app.set('view engine', 'js');
}

app.use(makara({
    i18n: {
        contentPath: path.resolve(__dirname, 'locales'),
        fallback: 'en-US'
    },
    specialization: {
        'oldtemplate': [
            {
                is: 'newtemplate',
                when: {
                    'testmode': 'beta'
                }
            }
        ]
    },
    localeContext: "makaraLocale"
}));

app.get('/path', function (req, res) {
    res.render('localizedtemplate');

    // Or

    makara.getBundler(req).get('contentbundle', function (err, data) {
        // Do something with err and data here
    });
});

Configuration

The middleware that sets up the Express view engine replacement engine-munger takes most of the configuration in makara.

  • i18n.contentPath - String, the root to search for content in. Required.
  • i18n.formatPath - Function, a function to convert a locale to a path fragment. Optional, defaults to one that returns country/language.
  • i18n.fallback - String or Object as bcp47 creates, the locale to use when content isn't found for the locale requested. Required.
  • enableMetadata - Boolean, defaults to false. Sets up metadata editing tags for integration with in-place content editing systems.
  • specialization - Object, the specialization rule map, in the form expected by karka.
  • cache - Boolean, defaults to false. Whether the dust engine should cache its views.
  • localeContext - String, defaults to locale. Specifies the key to the locale information in req object.

Content

Content intended for localization is stored in .properties files as simple key=value pairs.

These are the files that hold the content strings for the different languages your application supports.

Normally, you are likely to start with a master set of content (likely in English) and the localization process will populate corresponding files for the other languages you will need.

Placement of .properties files

The root of the .properties content files is the locales folder at the top level of your project. Under it will be a folder per country (as in US/, DE/, et cetera). Below each country folder is one or more language folders (as in en/, de/). So locales/US/en/ will be the likely location for your master set of .properties files.

.properties files are correlated with the dust templates that use them, by path and name.

If you have a top level index.dust file, its content .properties file will be at locales/US/en/index.properties This holds all the external content strings used by that template. If your template is at widgets/display.dust then the content for US English will be at locales/US/en/widgets/display.properties. If you have content you want to share across pages, then you should factor out use of that content into a separate partial and use that partial to achieve content sharing.

You can override this filename mapping by providing a formatPath function to the makara i18n configuration.

What's in a .properties file

The parser for this file format is spud.

The format is simple: key=value with one message per line encoded as UTF-8. Comments are prefixed with #.

Let's look at some samples and then use them to discuss various points.

index.properties file:

index.title=PayPal Merchant
index.callToAction=Enroll now!
index.greeting=Welcome {userName}

# A list
index.ccList[0]=Visa
index.ccList[1]=Mastercard
index.ccList[2]=Discover

# A map
index.states[AL]=Alabama
index.states[AK]=Alaska
index.states[AZ]=Arizona
index.states[CA]=California

We are using the name of the file to start our key on each line. This is strictly a convention that makes the path to the file clear. There's duplication between the two, but it makes debugging easier.

Text to the right of the = sign is a simple message string with the text of the message.

If you have runtime values to be inserted, use dust brace to select the value from the dust template context as in the index.greeting line. Note that there is no restriction on inserting HTML tags into the messages. They are just another string of characters as far as the content processing is concerned.

In addition to simple strings, we support lists and maps. The index.ccList above might be used to provide a list of values to go in a list of allowed credit cards.

The index.states might be used to populate a dropdown list of states with the key as the option tag value and the full state name as the visible text.

To support writing the key part in natural languages other than English, all UTF-8 characters are allowed with a few exceptions needed to make the key=value syntax work. The exceptions are:

  • No equal sign in key part (e.g. first equal sign starts the value)
  • No periods in key part (used to allow keys like a.b.c)
  • No square brackets (used for subscript and map key notation)
  • May not start with # (Used for comments)

These same general restrictions apply to map key values. If you need to use characters that are restricted, you can do so using either of these escaping mechanisms:

  • \udddd - Like JavaScript but only handles the same characters supported by this notation in JavaScript
  • \u{dddddd} - Like JavaScript ES6 notation and handles all possible Unicode characters

For example,

\u2603=snowman

would use the Unicode snowman character for the key name.

Key Promotion

There are some edge cases worth mentioning:

Case 1:

key.subkey=value
key.subkey[property]=value2

In this case, key.subkey is created originally as a string value but is then overridden as a map. The original value will be discarded.

Case 2:

key.subkey[0]=1
key.subkey[property]=value

In this case, key.subkey is created originally as a list but is then converted to a map when the alphanumeric key is added.

Referencing internationalized content from a dust template

This is done using the {@message} helper tag. A sample usage of @message is:

{@message type="content" key="index.title"/}

Lists and maps are bit trickier when it comes to inlining.

There are two approaches available. The first uses three additional attributes on the @message tag, before="xxx" and after="yyy" and sep="z". When emitting the list elements, each will be prefixed by the "before" string, if there is one, suffixed by the "after" string, if there is one, and separated by the "sep" string, if there is one. With sep, the last element is not followed by the separator. Note that the value {$idx} can be used in the before/after attribute strings and it will be replaced by the current iteration count when inlining the lists. Similarly, {$key} will be replaced with the current key when inlining a map. No replacement is done in the sep string.

In some cases inlining won't do, even with before/after/sep. For example, if you need to pass the list as a parameter to a templating partial that might implement a dropdown functionality.

For this, @message with a mode="paired" attribute offers more flexibility.

The mode="paired" parameter produces the content list such that you can use both the index of the element for the value in an option tag and the value for the displayable text.

The mode="paired" attribute delivers the content in the form of a JSON object, which in the case of a list of months might look like:

[{$id:0,$elt:"Jan"}, {$id:1,$elt:"Feb"},.. ]

This gives you more ability to work with both the list/map value and the element value in your template.

In addition to mode="paired" there is an alternate form, mode="json" This generates the content list or map as a standard JavaScript array or an object with properties, respectively.

For more on using mode="paired" see the advanced helper docs.

Contributing

Please see the contribution guide

makara's People

Contributors

alexsantos avatar aredridel avatar bluelnkd avatar gabrielcsapo avatar grawk avatar jasisk avatar jeffharrell avatar lensam69 avatar mathiasbynens avatar mstuart avatar paneraallday avatar pvenkatakrishnan avatar ravichandrasadineni avatar rragan avatar skoranga avatar skratchdot avatar snowinferno avatar submitteddenied avatar toksea avatar totherik avatar xjamundx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

makara's Issues

Express app stops responding if there are too many partial includes

It seems that makara does something strange that causes an express app to become unresponsive if multiple partial includes are used.

A sample app to illustrate this behaviour can be found in my github.
makara-bug

As far as I can tell this doesn't relate to adaro since the partials get resolved correctly. However the render function never finishes and the app just hangs without throwing any error.

Makara 2 and Dust @provide helper

I recently upgraded a Kraken project to Makara 2, and I discovered that the combination of mode="paired" and @provide does not work anymore.

I took me a while to figure out that @provide (from dustmotes-provide) is not able to consume the output of @message. I think that this breaking change should be mentioned somewhere (at least in this page).

If anyone is interested, I solved the problem by writing my own @provide helper: dust-provide-helper. It is not perfect, but it can be used as a drop-in replacement for dustmotes-provide with Makara 2.

Cache locale resolution

With caching disabled, the following formats are both supported:

res.locals.context = {
    locality: 'en_US'
};
res.locals.context = {
    locality: {
        country: 'US',
        language: 'en'
    }
};

however with cache enabled only the latter successfully resolves.

Language selection

What would be a good approach to give the user an option to set their language using this module ?

I thought about storing the language information in a cookie and then inject it into the response on each request using a middleware but is there a better approach ?

Problem with format path

Hi,
I have problem with convert a locale to a path fragment if the locale has only 2 chars (ex. cs (Czech)). It can't find the properties files in path ./locales/cs/index.properties (throw error Failed to lookup view). The path is correct.

With locale en_US everything works great.

Is this a bug?

So I would like to change i18n.formatPath but I can't to figure out how to do this in krakenjs. Can you help me, please?

Map in a list

it is possible to put a map in a list ?

in my properties file :

index.map[0].aa=foo
index.map[1].aa=bar

In this case the bundle of index return this :

{ map: [ 'foo', 'bar ] }

But would like something like that :

{ map: [{aa : 'foo'},{aa:  'bar'}]}

It is possible ?

I use makara with kraken-js.

Thanks !

Update bundalo for security issue

Hello

actually npm audit gives this

image

This is because in the package.json you use bundalo 0.2.9 which is dependent of a lodash vesion which is unsafe.

Could you at least upgrade to 1.0.0 since lodash seems to has been removed from this version.

Actually applications using makara (or krakenjs) are flagged insecure by npm audit...

The forward slashes of our dynamic partial path are being converted to HTML entities

Our application is using a layout template. If we supply a dynamic partial that has a forward slash in the path, somewhere during the dust rendering the forward slash is being converted to an HTML entity, so we get an error like the following:

Express
500 Error: ENOENT, open '/Users/hdoan/Sites/Source/OurApp/public/templates/someDirectory/anotherDirectory/myPage.dust'

dust helpers documentation is wrong

On the blog, you have this

"dust": {
    "helpers": [
        {
            "module": "dust-makara-helpers",
            "arguments": [ { "autoloadTemplateContent": false } ]
        }
    ]
}

It actually needs to be this

"dust": {
    "helpers": [{
        "name": "dust-makara-helpers",
        "arguments": { "autoloadTemplateContent": false }
    }]
},

Plan for makara deprecation

Would be good to have a scheduled rollout of makara deprecation possibly including:

  • documentation for making the switch, with a reference to doc from makara README
  • deprecation warning from makara
  • timeline/milestones

Weave edit tags optionally

The enableMetadata: true option allows to weave edit tags around content in a page. Is there some way by which I can retain content in properties files and still have makara not weave edit tags for few elements?

Upgrading makara: client side

In the "upgrading makara" guide, at the end it's written:

Adjust your client accordingly, and use dust-usecontent-helper and dust-message-helper or dust-intl to load the content for your templates.

But the README of these doesn't tell us how to use them in the browser so I'm a bit lost. Either these READMEs should be updated with client side examples or the upgrading makara guide should be a little bit more detailed (ideally both).

In the meantime, I'll continue investigating so maybe this issue will be transformed in a pull request in the helpers repo.

Sharing Content

From the docs:

"If you have content you want to share across pages, then you should factor out use of that content into a separate partial and use that partial to achieve content sharing."

Can you please explain this a bit ?

For example, if I have messages and want them to be available to every template, how do I do that ?

Example with two list values with same index

I see in #33 using the paired mode you can pass the JSON into the custom helper. I am curious how best to accomplish something without a select list, but dynamically displaying a list of anchor tags with tooltip.

Desired:

<span class="some-list">
<a href="#" title="l10n hint [0]">l10n label [0]</a>
<a href="#" title="l10n hint [1]">l10 lable [1]</a>
...
</span>

Properties:

filter.heading=Filter people by
peopleFilter[0]=ID
peopleFilterHint[0]=E.g. '1234'
peopleFilter[1]=Name
peopleFilterHint[1]=E.g. 'Mike' or 'Sally Jones'
peopleFilter[2]=Title
peopleFilterHint[2]=E.g. 'Broker'
peopleFilter[3]=Email
peopleFilterHint[3]=E.g. '[email protected]' or 'someco.com'

Ideally the template will iterate through the list of field names and display them as anchors but the tooltip will also be localized.

I tried the following that works only for anchors without paired mode, but cannot seem to get paired mode to work as in the #33 example.

Worked:

{@pre type="content" before="<a href='/'>" key="peopleFilter" after="</a>" sep=" " /}

Failed (still unsure how to reference 2 keys with same index?):

{@provide selected=chosen}
    {#peopleFilter}
    <a href="/">{$elt}</a>
    {/peopleFilter}
    {:peopleFilter}
    {@pre type="content" key="peopleFilter" mode="paired" /}
{/provide}

I guess one workaround would be to create a list of the full HTML anchor tags with hints but I figure there has to be a way to accomplish this. Suggestions appreciated and I figure this might be helpful to others as well.

Example for the use of mode="paired"

I can see the mention of mode="paired", but it's still not very clear on the use of it in dust template context. Can you add an example right under that section in README?

Dynamically passing content key from model to template

I read in #21 that you cannot pass in content key dynamically to a template. I am curious whether my issue in #35 could be solved by having a list of keys in the model object and the template could evaluate those keys and inject the proper content from the current resource bundle.

Example Model:

...
        filters: [
            {name_key:'filter.id', hint_key:'filter.hint.id'},
            {name_key:'filter.name', hint_key:'filter.hint.name'},
            {name_key:'filter.title', hint_key:'filter.hint.title'},
            {name_key:'filter.email', hint_key:'filter.hint.email'},
            ...
        ],
...

Example property bundle:

filter.id=ID
filter.hint.id=E.g. '1234'
filter.name=Name
filter.hint.name=E.g. 'Mike' or 'Sally Jones'
filter.title=Title
filter.hint.title=E.g. 'Broker'
filter.email=Email
filter.hint.email=E.g. '[email protected]' or 'someco.com'

On the template perhaps:

...

{#filters}
<a href='#' title='{@pre type="content" key="{hint_key}" /}'>{@pre type="content" key="{name_key}" /}</a>
{/filters}

...

I appreciate steer on how best to accomplish #35 and whether this might be possible but I'm missing something.

Single key locale fallback/overwrite

Looks like currently it is not possible to fallback to default locale for single keys, it would be nice to have this important feature.

Let say we have 2 locales with fallback to US_en:
US/en/layout/master.properties and GB/en/layout/master.properties

in US/en/layout/master.properties:

key1=value
key2=value
key3=value
key4=value

and for GB layout we want to overwrite only few keys , so in file GB/en/layout/master.properties:

key3=new value
key4=new value

in GB layout template, all keys that don't exist in GB's master.properties file render as key names: ☃key1☃ and ☃key2☃ with no values.

It would be very nice if those keys values can be populated automatically from fallback locale bundle so we don't have to add/repeat them in all other locales.

We use makara with kraken-js.

Locale specific templates

Let's say I would like to make a separate template file per locale in a Kraken application. Something like this:

/templates
  /US   -??
    myview.dust
  /GB   -??
    myview.dust

And properties structure like

/US
  /en
     myview.properties
/GB
  /en
     myview.properties

Do I need to specify a custom Makara formatPath function, or should there be some other approach?

bundle.get() variables

Hi,

Can someone show me how to use bundle.get() with variables? I tried the following to no avail, and I was unable to find any examples which use them.

bundle.get('login.success_message', { username: 'Nathan' })

Does such functionality exist? The above prints "You are now logged in as {username}."

Thanks.

Question: How to effectively manage HTML, DRY, and whitespace with Makara?

I’ve encountered a common localization issue that I’ve been unable to solve with Makara and Dust.

Issues I’m trying to address:

  • How do I keep HTML in the template and out of the properties file (see below: the links to terms of sale and privacy policy)?
  • How do I reference properties in other properties (see below: reuse the “Pay Now” text)?
  • How do I manage whitespace (CJK versus western languages)?

The first two are both attempts to DRY things up as well as keep markup in the domain of front end engineers and out of the hands of localization editors. The third is an attempt to not require trailing whitespace in property values, e.g., common.grammar.comma=,  (Makara; note the trailing whitespace after the comma) versus common.grammar.comma={0}, {1} (Java).

I don’t see a way to accomplish this without splitting the disclaimer into multiple properties then stitching them back together. Note that this would require saving trailing whitespace in the properties files for some locales (unfortunate since most IDEs will strip it). Also, this solution won’t work with all strings, as the order of the “pieces” sometimes changes from locale to locale (especially with CJK).

payment.disclaimer.a=By clicking “
payment.submit=Buy Now
# Note the trailing whitespace
payment.disclaimer.b=,” you agree to the 
payment.disclaimer.c=Terms of Sale
# Note the leading and trailing whitespace
payment.disclaimer.d= and 
payment.disclaimer.e=Privacy Policy
payment.disclaimer.f=.

Is what I want to accomplish even possible? Do I just need to write a custom helper?

To clarify what I’m asking, here’s a real-world example using Java and FreeMarker:

<!-- payment.ftl -->
<#assign tosLink>
    <a href="/${locale}/termsofsale" tabindex="1">${msg("payment.disclaimer.tosLink")}</a>
</#assign>
<#assign privacyLink>
    <a href="/${locale}/termsofsale" tabindex="1">${msg("payment.disclaimer.privacyLink")}</a>
</#assign>
<p>${msg("payment.disclaimer.text", [msg("payment.submit"), tosLink, privacyLink], false)}</p>
<button class="btn btn-primary btn-wide" id="payment-submit" tabindex="1">${msg("payment.submit")}/button>
# payment_en_US.properties
payment.disclaimer.text=By clicking “{0},” you agree to the {1} and {2}.
payment.disclaimer.tosLink=Terms of Sale
payment.disclaimer.privacyLink=Privacy Policy
payment.submit=Pay Now
# payment_en_GB.properties
payment.disclaimer.text=By clicking ‘{0}’, you agree to the {1} and {2}.
payment.disclaimer.tosLink=Terms of Sale
payment.disclaimer.privacyLink=Privacy Policy
payment.submit=Pay Now
# payment_fr_FR.properties
payment.disclaimer.text=En cliquant sur «&#160;{0}&#160;», vous acceptez les {1} et la {2}.
payment.disclaimer.tosLink=Conditions de Vente
payment.disclaimer.privacyLink=Politique de Confidentialité
payment.submit=Payer
# payment_ko_KR.properties
payment.disclaimer.text=“{0}”를 눌러 {1},{2}에 동의합니다.
payment.disclaimer.tosLink=대한민국 거주자에 대한 판매 조건
payment.disclaimer.privacyLink=개인정보 취급방침
payment.submit=구매하기
# payment_zh_TW.properties
payment.disclaimer.text=點擊「{0}」代表您同意{1}與{2}。
payment.disclaimer.tosLink=銷售協議
payment.disclaimer.privacyLink=隱私權政策
payment.submit=現在付款

Desired output:

<!-- en_US -->
<p>By clicking “Pay Now,” you agree to the <a href="/en-us/termsofsale" tabindex="1">Terms of Sale</a> and <a href="/en-us/privacy" tabindex="1">Privacy Policy</a>.</p>
<button class="btn btn-primary btn-wide" id="payment-submit" tabindex="1">Pay Now</button>
<!-- en_GB -->
<p>By clicking ‘Pay Now’, you agree to the <a href="/en-gb/termsofsale" tabindex="1">Terms of Sale</a> and <a href="/en-gb/privacy" tabindex="1">Privacy Policy</a>.</p>
<button class="btn btn-primary btn-wide" id="payment-submit" tabindex="1">Pay Now</button>
<!-- fr_FR -->
<p>En cliquant sur «&#160;Payer&#160;», vous acceptez les <a href="/fr-fr/termsofsale" tabindex="1">Conditions de Vente</a> et la <a href="/fr-fr/privacy" tabindex="1">Politique de confidentialité</a>.</p>
<button class="btn btn-primary btn-wide" id="payment-submit" tabindex="1">Payer</button>
<!-- ko_KR -->
<p>“구매하기”를 눌러 <a href="/ko-kr/termsofsale" tabindex="1">대한민국 거주자에 대한 판매 조건</a>,<a href="/ko-kr/privacy" tabindex="1">개인정보 취급방침</a>에 동의합니다.</p>
<button class="btn btn-primary btn-wide" id="payment-submit" tabindex="1">구매하기</button>
<!-- zh_TW -->
<p>點擊「現在付款」代表您同意<a href="/zh-tw/termsofsale" tabindex="1">銷售協議</a>與<a href="/zh-tw/privacy" tabindex="1">隱私權政策</a>。</p>

makara doesn't general edit tags in non-DEV mode

In dev mode, makara sees the i18n config specifying enableMetadata and functions correctly. However, when the grunt build scripts run and pre-compile the templates, they do not take the config into consideration so all dust templates lack the metadata desired

Makara 2 with locale from cookie is not localizing templates

Hi, I'm following the i18n example and makara 2.0 blog post / docs. but I'm not able to override the fallback locale in my kraken. Probably I'm missing something.

I have my middleware to read locale from cookies and setting it in the res.locals.locale and req.locale .

'use strict';
var bcp47 = require('bcp47');

module.exports = function () {
    return function (req, res, next) {
        var locale = req.cookies && req.cookies.locale;
        //Set the locality for this response. The template will pick the appropriate bundle
        res.locals.locale = req.locale = bcp47.parse(locale);        
        //res.locals.locale = req.locale = locale //I have tried also this 

        next();
    };
};

And in my config.json I have:

"locale": {
    "priority": 95,
    "enabled": true,
    "module": {
        "name": "path:./lib/locale"
    }
}

I have declared a route to set locale cookie into my index.js controller (usage eg: /setLanguage/EN-us )

router.get('/setLocale/:locale', function (req, res) {
    res.cookie('locale', req.params.locale);
    res.redirect('/');
});

The middleware works fine, and sets res.locals.locale and req.locale to the bcp47 object according to the locale cookie value.
But on the template rendering I always get the default locale message, and not my localized message taken from the correct .properties files.

I'm missing something or does it looks correct?

is there a concept of fallback at the level of the Country

so, let's say that you support GB (UK) but you only support one language (en) but for some reason a user has french in the accept-language header and country=GB, so i don't want it to fallback to fr-FR, i want it to fallback to en-GB, is that possible?

Unable to use latest dustjs version due to package.json conflict in makara

When deploying a build to heroku, the compile/deploy step fails due to a version conflict between my package.json containing the latest (2.3.x) of dustjs-linkedin and the specified 2.0.0 version in Makara. There is a similar problem with the declared version of dustjs-linkedin in the Adaro package.json.

I'd suggest setting them to use 2.x.x instead of explicit versions and only make it more restrictive if it's found LinkedIn changed the dust signature/API.

Build task on windows fails due to OS path separator issue

The grunt-makara-amdify 1.0.1 uses the makara-builder 1.0.0 and in makara-builder/index.js I can see:

    var locales = paths.map(function (p) {
        var m = /(.*)\/(.*)/.exec(path.relative(localeRoot, p));
        return m[2] + '-' + m[1];
    });

localeRoot="...\locales" and p="...locales/DE/de"

The path.relative() call transforms p into windows style and returns "DE\de".
The reg ex evaluation returns null because of the hardcoded linux path sep.
The following line gives of course "Fatal error: Cannot read property '2' of null".

Any hint for a workaround? Beside "use linux" ... ;-)

is makara only for dustjs template engine?

in README, it says: There's nothing inherently dust-centric about makara, but it does provide dust template engines as a default.
So, dustjs template engine will get installed even if i am using react.

Breaking: Remove support for mode=json

I think we can eliminate the feature entirely: It's used seldom and when it's used, it's mostly abused. Quoting takes more contextual awareness than a dust helper can give.

strawman for a new bundle format

JSON syntax (which isn't so relevant, since anything that has strings and nested arrays and objects can support the same semantics) :

login.json

{
    "login": {
        "username": "Username",
        "brandname": { "value": "Brand Name(tm)", "do_not_translate": true }
    },
    "includes": [
        "form.json"
    ]
}

form.json

{
    "submit": "Submit",
    "error": "there was a error!"
}

Includes could be used as a fallback mechanism, too, explicitly forming a relationship between resource files, rather than any implicit or higher level relationship between language files.

CSON:

"login":
    "username": "Username"
    "brandname":
        "value": "Brand Name(tm)"
        "do_not_translate": true
"includes": [
    "form.json"
]

YAML:

"login":
    "username": "Username"
    "brandname":
        "value": "Brand Name(tm)"
         "do_not_translate": true
"includes":
    - form.json

Properties with comment annotations:

login.username=Username
login.brandname=Brand Name(tm) # @do_not_translate=true
include=form.json

Dynamic content keys

In Dust, we can do this to make a dynamic partial reference:

{>"flowViews/flowView{flowName}" /}

But sadly, we can't do this:

{@pre type="content" key="myprefix{countryCode}.mykey" /}

It would be more native-like behavior to allow content keys to be dynamic and allow us a way of avoiding logical structures in the Dust code.

Build Task fails on windows due to OS separator

Looks like Grunt expands patterns like **/*.dust and **\\*.dustwith no regard to the host OS path separator. It's always a /

Under Windows, this causes issues with the following code:

Proper solution: Find a way for the globbing to respect the OS separator.

Very ugly workaround 💩 : Assume that everything works with /. Don't like the brittleness of this and would only use it as a last resort.

Makara doesn't look up localised templates

Either I am missing something or makara seems to be broken. I followed the guide in the read me and set up makara as view engine:

// ...snip
const dustConfig = {
    cache: !config.development,
    helpers: [
        "dustjs-helpers",
        "dust-makara-helpers",
        debug,
        resolve(app),
        inline,
        adv
    ]
};

if (app.get("env") === "development") {
    app.set("views", path.join(config.root, "app/views"));
    app.engine("dust", makara.dust(dustConfig));
    app.set("view engine", "dust");
} else {
    // use cached, precompiled templates
    app.set("views", path.join(config.root, "build/app/views"));
    app.engine("js", makara.js(dustConfig));
    app.set("view engine", "js");
}

app.use(makara({
    i18n: {
        contentPath: path.join(config.root, "locales"),
        fallback: "de-DE"
    }
}));
// ...snip

Folder structure is ./build/app/views/DE/de/kaufberatung.js and so on.
Looking at the debug output it seems that makara isn't even trying to look into the language folders.

ENGINE-MUNGER 24031: specialization mapped 'kaufberatung.js' to 'kaufberatung.js'
ENGINE-MUNGER 24031: lookup "kaufberatung.js"
ENGINE-MUNGER 24031: stat "~/workspace/project/build/app/views/kaufberatung.js"
ENGINE-MUNGER 24031: stat "~/workspace/project/build/app/views/kaufberatung.js/index.js"

Looking at the code in makara/index.js it seems like there should be some code to setup i18n for .js files but all I can find is the .properties setup.

Question: what are the various ways to manually set the expressjs-res's locale

(x-post from engine-munger)

I'm using makara in a kraken (yo generated) application. Presently looking for some documentation to find the right approach to manually set the i18n of the express.js http response object. So that right .properties file gets picked-up based on the business logic.

Below is one method I found by trail and error, where the GB version of properties file gets picked-up correctly even though my browser has Accept-Language for US locale.

res.render('index', { name: 'index', locale: 'en_GB'});

However, not certain if this is the right way, or could there be some situation that I'm unaware of during the run time where (user/browser settings, or, ..?) the above approach will get overridden and an incorrect .properties file will get picked up?

Question:

  1. Can someone please point me to any documentation which explains how the locale can be manually set from a kraken-node-MVC-controller?
  2. If there are various ways, then which approach gets the highest priority?

I can't pass the enableMetadata parameter

Hi, I have spent several hours trying to set enableMetadata parameter to true but I can't find how to do it.

I have tried several configuration options without success like:

"middleware": { "makara": { "priority": 100, "enabled": true, "module": { "name": "makara", "arguments": [ { "i18n": "config:i18n", "specialization": "config:specialization" "enableMetadata": "true" } ] } },
...

While debugging, I have the options parameter in dust-message-helper as undefined.

What can I do?

Common resource keys

I know the docs says this:

"If you have content you want to share across pages, then you should factor out use of that content into a separate partial and use that partial to achieve content sharing."

But I don't believe this makes any sense. As an example, I simply would like the word 'login' to use a common.login key. Surely it would be breaking the principles of DRY to replicate this key based on the location in which you are using it and likewise it is overkill to create a partial for one individual key.

I was wondering if this limitation is ever likely to change or if you have good reason for it that I am unaware of.

Thanks!
Matt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.