Skip to content

Instantly share code, notes, and snippets.

@XmlmXmlmX
Last active February 14, 2020 17:50
Show Gist options
  • Save XmlmXmlmX/011f11a3aec7382cfed75c9a398507be to your computer and use it in GitHub Desktop.
Save XmlmXmlmX/011f11a3aec7382cfed75c9a398507be to your computer and use it in GitHub Desktop.
A Panini Localization Helper

A Panini Localization Helper

This helper helps you to localize your email templates created with zurbs panini. Currently this helper will only work in a custom clone of the panini code and not as a panini-helper as described here.

Installation

Make a clone of the panini source

git clone https://github.com/zurb/panini.git

Add the localization.js to the helpers folder.

Register the new handler in render.js#61:

this.Handlebars.registerHelper('localize', require('../helpers/localize')(pageData.page));

Now reference your extended clone in your email project package.json.

How it works

The helper is searching for statements like this {{#localize}}paragraphXY{{/localize}}. paragraphXY is the key inside the localize JSON. Based on the current page-name the helper will look up in the localization folder for files with the same name. But it is a little bit smarter. It will also look for files wich start with the same string. If your page is called for example Foo.Bar.Page1.pl-PL.html, the following localization files will be crawled:

  • Foo.json
  • Foo.PL.json
  • Foo.pl-PL.json
  • Foo.Bar.json
  • Foo.Bar.PL.json
  • Foo.Bar.Page1.json
  • Foo.Bar.Page1.PL.json
  • Foo.Bar.Page1.pl-PL.json

Why would it do it such like that?

Let's say you have a very common localization string like a contact email wich is for all your emails in all languages the same. And you don't want to put this email address inside the partial or template. Now you can put this email into Foo.json. But for a single language your want an other email address, just override it in Foo.pl-PL.sjon.

Another scenario could be to have a email for a whole country, then put this into Foo.us.json for example. Now all us pages will inherit this value (unless they do not have their own value).

What's inside the localization JSON?

Very straight forward - use key and value:

{
    "key1": "hello",
    "key2": "world"
}

Example how to structure your Email Project for localization

You can create your project with the following structure:

Layouts

src\layouts\Brand1.Project.html
src\layouts\Brand2.Project.html

Localization (new)

src\localization\Brand1.Project.json
src\localization\Brand1.Project.en.json
src\localization\Brand1.Project.en-US.json
src\localization\Brand1.Project.de.json
src\localization\Brand1.Project.de-DE.json
src\localization\Brand1.Project.de.json
src\localization\Brand1.Project.Page1.json
src\localization\Brand1.Project.Page1.en.json
src\localization\Brand1.Project.Page1.en-US.json
src\localization\Brand1.Project.Page1.de.json
src\localization\Brand1.Project.Page1.de-DE.json
src\localization\Brand1.Project.Page1.de.json

Pages

src\pages\Brand1.Project.Page1.html
src\pages\Brand1.Project.Page1.en.html
src\pages\Brand1.Project.Page1.en-US.html
src\pages\Brand1.Project.Page1.de.html
src\pages\Brand1.Project.Page1.de-DE.html
src\pages\Brand1.Project.Page1.de.html

Partials

src\pages\Brand1.Project.Page1.html (contains the page content)
src\pages\Brand1.Project.Page1.us.html (contains us-specific stuff like other address format)
var fs = require('fs');
var path = require('path');
var gutil = require('gulp-util');
/**
* Generates a Handlebars block helper called #localize for use in templates. This helper must be re-generated for every page that's rendered, because the return value of the function is dependent on the name of the current page.
* @param {string} pageName - Name of the page to use in the helper function.
* @returns {function} A Handlebars helper function.
*/
module.exports = function(pageName) {
/**
* Handlebars block helper that localizes the key wich is inside of it based on the current page.
* @param (object) options - Handlebars object.
* @example
* {{#localize}}localizationKey{{/localize}}
* @return The content inside the helper if a page matches, or an empty string if not.
*/
return function() {
var params = Array.prototype.slice.call(arguments);
var _localizationFileName = params.slice(0, -1)[0];
var options = params[params.length - 1];
var localizationKey = options.fn(this).trim().replace(/\r?\n|\r/g, '');
var split = null;
var localKeyRegex = /^[a-z]{2,3}(?:-[A-Z]{2,3}(?:-[a-zA-Z]{4})?)?$/;
var locale = null;
var fileNames = [];
var country = null;
var language = null;
var _fileNames = [];
var localizationFileName = null;
var returnValue = null;
var localizationFile = null;
if (typeof _localizationFileName === 'undefined' || _localizationFileName === null || _localizationFileName === '' || _localizationFileName.length === 0) {
_localizationFileName = pageName;
}
split = _localizationFileName.toString().split('.');
if (split[split.length - 1] === 'html' || split[split.length - 1] === 'cshtml') {
split.splice(split.length - 1, 1);
}
if (localKeyRegex.test(split[split.length - 1])) {
locale = split.splice(split.length - 1, 1)[0];
}
if (locale !== null && locale.includes('-')) {
var localeSplit = locale.split('-');
if (localeSplit.length > 1) {
language = localeSplit[0];
country = localeSplit[1];
}
}
split.forEach(function(currentValue, index, array) {
if (localizationFileName === null) {
localizationFileName = currentValue;
} else {
localizationFileName += `.${currentValue}`;
}
_fileNames.push(localizationFileName);
if (language !== null) {
_fileNames.push(localizationFileName + '.' + language);
}
if (locale !== null) {
_fileNames.push(localizationFileName + '.' + locale);
}
});
fileNames = _fileNames;
fileNames.forEach(function(currentValue, index, array) {
var filePath = path.join(process.cwd(), `./src/localization/${currentValue}.json`);
try {
var ext = path.extname(filePath);
var name = path.basename(filePath, ext);
delete require.cache[require.resolve(filePath)];
var data = require(filePath);
if (data !== null) {
var localString = data[localizationKey];
if (typeof localString !== 'undefined' && localString !== null && localString !== '') {
returnValue = localString;
}
}
} catch (e) {
//gutil.log(`Localization file "${filePath}" not found.`);
}
});
if (returnValue !== null) {
return returnValue;
} else {
gutil.log(gutil.colors.red(`Error: Resource with key "${localizationKey}" for page "${pageName}" not found, sorry.`));
return localizationKey;
}
}
}
@GoodNew5
Copy link

how it work?

@GoodNew5
Copy link

GoodNew5 commented Feb 16, 2018

if i want get pages name-template.ru.html, name-template.en.html on output without doublecated files with different translate

@GoodNew5
Copy link

and if i have json files (en.json, ru.json, etc)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment