├── test ├── fixtures │ ├── data │ │ ├── i18n.json │ │ ├── license.json │ │ ├── i18n │ │ │ ├── en.json │ │ │ ├── fr.json │ │ │ └── es.json │ │ └── i18n-alt.json │ └── templates │ │ ├── layouts │ │ ├── alt.hbs │ │ └── default.hbs │ │ ├── without-plugin │ │ └── index.hbs │ │ ├── index.hbs │ │ └── with-plugin │ │ └── index.hbs ├── actual │ ├── without-plugin │ │ ├── en.html │ │ ├── es.html │ │ ├── fr.html │ │ └── index.html │ ├── with-permalinks │ │ ├── en │ │ │ └── index.html │ │ ├── fr │ │ │ └── index.html │ │ └── es │ │ │ └── index.html │ ├── with-list-of-languages │ │ ├── index-en.html │ │ ├── index-fr.html │ │ └── index-es.html │ └── with-plugin │ │ ├── index-en.html │ │ ├── index-fr.html │ │ └── index-es.html └── main-test.js ├── .travis.yml ├── .gitignore ├── .gitattributes ├── .editorconfig ├── .verb.md ├── index.js ├── lib └── i18n.js ├── package.json ├── Gruntfile.js └── README.md /test/fixtures/data/i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "languages": [ 3 | "en", 4 | "es", 5 | "fr" 6 | ] 7 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | before_script: 5 | - npm install -g grunt-cli 6 | -------------------------------------------------------------------------------- /test/fixtures/data/license.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "MIT", 3 | "copyright": "Copyright (c) 2014 Assemble, contributors. Released under the MIT license" 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | node_modules 3 | *.sublime-* 4 | *.swp 5 | 6 | # Ignore the staging dir for docs 7 | 8 | tmp 9 | docs 10 | vendor 11 | TODO.md 12 | *.rar 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | * text eol=lf 3 | 4 | # binaries 5 | *.ai binary 6 | *.psd binary 7 | *.jpg binary 8 | *.gif binary 9 | *.png binary 10 | *.jpeg binary -------------------------------------------------------------------------------- /test/fixtures/templates/layouts/alt.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{i18n "title"}} 5 | 6 | 7 | {{> body }} 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/data/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "en", 3 | "title": "i18n - English", 4 | "description": "This example demonstrates the creation of multiple pages based on one template and many i18n files" 5 | } -------------------------------------------------------------------------------- /test/fixtures/data/i18n/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "fr", 3 | "title": "i18n - Français", 4 | "description": "Cet exemple démontre la création de multiple page basée sur un modèle et plusieurs fichiers i18n." 5 | } -------------------------------------------------------------------------------- /test/fixtures/data/i18n/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "es", 3 | "title": "i18n - Español", 4 | "description": "Este ejemplo muestra la creación de una página múltiple basada en el número de modelo y los archivos i18n." 5 | } -------------------------------------------------------------------------------- /test/fixtures/templates/layouts/default.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{i18n "title"}} 6 | 7 | 8 | {{> body }} 9 | 10 | -------------------------------------------------------------------------------- /test/actual/without-plugin/en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | Is english your language of choice? 9 | 10 | -------------------------------------------------------------------------------- /test/actual/without-plugin/es.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | ¿Es español el idioma de su elección? 9 | 10 | -------------------------------------------------------------------------------- /test/actual/without-plugin/fr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | Est-français la langue de votre choix? 9 | 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [test/fixtures/*] 16 | insert_final_newline = false 17 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /test/fixtures/templates/without-plugin/index.hbs: -------------------------------------------------------------------------------- 1 | --- 2 | lang: <%= language %> 3 | copyright: Copyright (c) 2014 Assemble, contributors. Released under the MIT license 4 | footnote: My language is set to <%= language %> 5 | --- 6 |

{{i18n "title"}}

7 |

{{i18n "description"}}

8 | 12 | -------------------------------------------------------------------------------- /test/fixtures/templates/index.hbs: -------------------------------------------------------------------------------- 1 | --- 2 | lang: <%= language %> 3 | copyright: Copyright (c) 2014 Assemble, contributors. Released under the MIT license 4 | footnote: My language is set to <%= language %> 5 | --- 6 |

{{i18n "title"}}

7 |

{{i18n "description"}}

8 | 13 | -------------------------------------------------------------------------------- /.verb.md: -------------------------------------------------------------------------------- 1 | # {%= name %} {%= badge("fury") %} {%= badge("travis") %} 2 | 3 | > {%= description %} 4 | 5 | {%= include("install", {save: '--save'}) %} 6 | 7 | ## Other grunt-assemble plugins 8 | {%= related(verb.related.list, {remove: name}) %} 9 | 10 | ## Contributing 11 | {%= include("contributing") %} 12 | 13 | ## Author 14 | {%= include("author") %} 15 | 16 | ## License 17 | {%= copyright() %} 18 | {%= license() %} 19 | 20 | *** 21 | 22 | {%= include("footer") %} 23 | -------------------------------------------------------------------------------- /test/actual/without-plugin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | 9 |

i18n - Français

10 |

Cet exemple démontre la création de multiple page basée sur un modèle et plusieurs fichiers i18n.

11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/actual/with-permalinks/en/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - English 6 | 7 | 8 | 9 |

i18n - English

10 |

This example demonstrates the creation of multiple pages based on one template and many i18n files

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/actual/with-permalinks/fr/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | 9 |

i18n - Français

10 |

Cet exemple démontre la création de multiple page basée sur un modèle et plusieurs fichiers i18n.

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/actual/with-list-of-languages/index-en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - English 6 | 7 | 8 | 9 |

i18n - English

10 |

This example demonstrates the creation of multiple pages based on one template and many i18n files

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/actual/with-list-of-languages/index-fr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | 9 |

i18n - Français

10 |

Cet exemple démontre la création de multiple page basée sur un modèle et plusieurs fichiers i18n.

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/actual/with-permalinks/es/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Español 6 | 7 | 8 | 9 |

i18n - Español

10 |

Este ejemplo muestra la creación de una página múltiple basada en el número de modelo y los archivos i18n.

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/actual/with-list-of-languages/index-es.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Español 6 | 7 | 8 | 9 |

i18n - Español

10 |

Este ejemplo muestra la creación de una página múltiple basada en el número de modelo y los archivos i18n.

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/fixtures/templates/with-plugin/index.hbs: -------------------------------------------------------------------------------- 1 | --- 2 | lang: <%= language %> 3 | copyright: <%= license.copyright %> 4 | footnote: My language is set to <%= language %> 5 | lodash: <%= i18n[language].title %> 6 | --- 7 |

{{i18n "title"}}

8 |

{{i18n "description"}}

9 |

{{lodash}}

10 | 21 | -------------------------------------------------------------------------------- /test/fixtures/data/i18n-alt.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "alt.hbs", 3 | "languages": [ 4 | { 5 | "filename": "en", 6 | "data": "<%= _.expand('./data/i18n/en.json') %>", 7 | "content": "Is english your language of choice?" 8 | }, 9 | { 10 | "filename": "es", 11 | "data": "<%= _.expand('./data/i18n/es.json') %>", 12 | "content": "¿Es español el idioma de su elección?" 13 | }, 14 | { 15 | "filename": "fr", 16 | "data": "<%= _.expand('./data/i18n/fr.json') %>", 17 | "content": "Est-français la langue de votre choix?" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /test/actual/with-plugin/index-en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - English 6 | 7 | 8 | 9 |

i18n - English

10 |

This example demonstrates the creation of multiple pages based on one template and many i18n files

11 |

i18n - English

12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/actual/with-plugin/index-fr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Français 6 | 7 | 8 | 9 |

i18n - Français

10 |

Cet exemple démontre la création de multiple page basée sur un modèle et plusieurs fichiers i18n.

11 |

i18n - Français

12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/actual/with-plugin/index-es.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n - Español 6 | 7 | 8 | 9 |

i18n - Español

10 |

Este ejemplo muestra la creación de una página múltiple basada en el número de modelo y los archivos i18n.

11 |

i18n - Español

12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * grunt-assemble-i18n 3 | * 4 | * Copyright (c) 2014-2015, Jon Schlinkert. 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | var _ = require('lodash'); 9 | var i18n = require('./lib/i18n'); 10 | var helper = require('handlebars-helper-i18n'); 11 | 12 | var options = { 13 | stage: 'assemble:post:data' 14 | }; 15 | 16 | /** 17 | * postprocess 18 | * @param {Object} params 19 | * @param {Function} callback 20 | */ 21 | module.exports = function (params, callback) { 22 | 'use strict'; 23 | 24 | var grunt = params.grunt; 25 | 26 | grunt.verbose.subhead('Running:'.bold, '"assemble-contrib-i18n"'); 27 | grunt.verbose.writeln('Stage: '.bold, '"' + params.stage + '"\n'); 28 | 29 | grunt.verbose.writeln('Loading the i18n helper'); 30 | params.assemble.engine.registerFunctions(helper.i18n); 31 | 32 | var opts = params.assemble.options.i18n; 33 | grunt.verbose.writeln('Options: '.bold, require('util').inspect(opts)); 34 | 35 | if (opts) { 36 | var o = {}; 37 | var data = params.assemble.options.data; 38 | var templates = opts.templates; 39 | var languages = opts.languages; 40 | var defaultLanguage = opts.defaultLanguage; 41 | 42 | if (opts.data) { 43 | o.data = opts.data; 44 | } 45 | 46 | if (templates) { 47 | o.templates = templates; 48 | } 49 | 50 | if (languages) { 51 | o.languages = languages; 52 | } 53 | 54 | if (defaultLanguage) { 55 | o.defaultLanguage = defaultLanguage; 56 | } 57 | 58 | var pages = i18n(data, o); 59 | 60 | grunt.verbose.writeln('Pages: '.bold, require('util').inspect(pages)); 61 | params.assemble.options.pages = _.extend({}, (params.assemble.options.pages || {}), pages); 62 | 63 | } 64 | 65 | callback(); 66 | }; 67 | 68 | module.exports.options = options; 69 | -------------------------------------------------------------------------------- /lib/i18n.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var path = require('path'); 3 | var file = require('fs-utils'); 4 | var matter = require('gray-matter'); 5 | 6 | module.exports = function (data, options) { 7 | // Specify and exapnd the template(s) to use for each language 8 | var templates = file.expand(options.templates = options.templates || ['templates/*.hbs']); 9 | 10 | var pages = {}; 11 | 12 | var languages = options.languages || []; 13 | 14 | var defaultLanguage = options.defaultLanguage || ''; 15 | 16 | var process = function () { 17 | var i18n = []; 18 | 19 | //Adds the i18n context 20 | languages.forEach(function (language) { 21 | i18n[language] = _.extend({}, data[language]); 22 | }); 23 | 24 | // Iterate over the languages 25 | languages.forEach(function (language) { 26 | 27 | templates.forEach(function (page) { 28 | var ext = path.extname(page); 29 | var pageObj = matter.read(page); 30 | 31 | i18n = _.extend({}, i18n, {languages: languages}); 32 | 33 | var context = _.extend({}, data, {language: language, i18n: i18n}, pageObj.context); 34 | var filename = defaultLanguage !== language ? page.replace(ext, "-" + language + ext) : page; 35 | 36 | pages[filename] = { 37 | filename: filename, 38 | content: pageObj.content, 39 | data: context 40 | }; 41 | 42 | }); 43 | }); 44 | }; 45 | 46 | if (options.data) { 47 | var filepaths = file.expand(options.data); 48 | 49 | _.each(filepaths, function (filepath, index) { 50 | 51 | // Read in the data from each file 52 | var i18nData = file.readDataSync(filepath); 53 | 54 | if (i18nData.languages) { 55 | languages = _.union(languages, i18nData.languages || []); 56 | } else { 57 | var languageKey = path.basename(filepath, path.extname(filepath)); 58 | data[languageKey] = i18nData; 59 | } 60 | }); 61 | } 62 | 63 | process(); 64 | 65 | return pages; 66 | }; 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-assemble-i18n", 3 | "description": "Plugin for adding i18n support to Assemble projects.", 4 | "version": "0.1.1", 5 | "homepage": "https://github.com/assemble/grunt-assemble-i18n", 6 | "author": { 7 | "name": "Jon Schlinkert", 8 | "url": "https://github.com/assemble/grunt-assemble-i18n" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/assemble/grunt-assemble-i18n" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/assemble/grunt-assemble-i18n/issues" 16 | }, 17 | "license": { 18 | "type": "MIT", 19 | "url": "https://github.com/assemble/assemble-contrib-permalinks/blob/master/LICENSE" 20 | }, 21 | "files": [ 22 | "index.js", 23 | "lib/" 24 | ], 25 | "main": "index.js", 26 | "scripts": { 27 | "test": "grunt test" 28 | }, 29 | "dependencies": { 30 | "fs-utils": "~0.3.6", 31 | "gray-matter": "~0.2.8", 32 | "handlebars-helper-i18n": "^0.1.0", 33 | "lodash": "~2.4.1" 34 | }, 35 | "devDependencies": { 36 | "grunt": "~0.4.2", 37 | "grunt-contrib-clean": "~0.5.0", 38 | "grunt-assemble": "~0.4.0", 39 | "grunt-assemble-permalinks": "~0.1.0", 40 | "handlebars": "~1.3.0", 41 | "grunt-mocha-test": "~0.10.0", 42 | "chai": "~1.9.1", 43 | "cheerio": "~0.13.1" 44 | }, 45 | "keywords": [ 46 | "assemble", 47 | "assemblecontribcollection", 48 | "assembleplugin", 49 | "i18n", 50 | "internationalize", 51 | "language", 52 | "local", 53 | "localize", 54 | "plugin" 55 | ], 56 | "verb": { 57 | "related": { 58 | "list": [ 59 | "grunt-assemble", 60 | "grunt-assemble-anchors", 61 | "grunt-assemble-contextual", 62 | "grunt-assemble-decompress", 63 | "grunt-assemble-download", 64 | "grunt-assemble-i18n", 65 | "grunt-assemble-lunr", 66 | "grunt-assemble-navigation", 67 | "grunt-assemble-permalinks", 68 | "grunt-assemble-sitemap", 69 | "grunt-assemble-toc", 70 | "grunt-assemble-wordcount" 71 | ] 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | var pages = require('./lib/i18n'); 5 | 6 | var read = function(src) { 7 | return grunt.file.readJSON(src); 8 | }; 9 | 10 | grunt.util._.mixin({ 11 | read: read, 12 | expand: function(src) { 13 | return grunt.file.expand(src).map(read); 14 | } 15 | }); 16 | 17 | // Project configuration. 18 | grunt.initConfig({ 19 | 20 | i18n_alt: grunt.file.readJSON('test/fixtures/data/i18n-alt.json'), 21 | 22 | assemble: { 23 | options: { 24 | plugins: ['./index.js'], 25 | data: 'test/fixtures/data/**/*.json', 26 | flatten: true, 27 | partials: 'test/fixtures/templates/includes/*.hbs', 28 | layoutdir: 'test/fixtures/templates/layouts', 29 | layout: 'default.hbs' 30 | }, 31 | 32 | "without-plugin": { 33 | options: { 34 | language: 'fr', 35 | pages: '<%= i18n_alt.languages %>' 36 | }, 37 | files: {'test/actual/without-plugin/': ['test/fixtures/templates/without-plugin/*.hbs']}, 38 | }, 39 | 40 | "with-plugin": { 41 | options: { 42 | i18n: { 43 | data: ['test/fixtures/data/i18n.json', 'test/fixtures/data/i18n/*.json'], 44 | templates: ['test/fixtures/templates/with-plugin/*.hbs'] 45 | } 46 | }, 47 | dest: 'test/actual/with-plugin/', 48 | src: '!*.*' 49 | }, 50 | 51 | "with-permalinks": { 52 | options: { 53 | plugins: ['index.js', 'grunt-assemble-permalinks'], 54 | i18n: { 55 | data: 'test/fixtures/data/i18n.json', 56 | templates: ['test/fixtures/templates/*.hbs'] 57 | }, 58 | permalinks: { 59 | structure: ':language/index.html' 60 | } 61 | }, 62 | dest: 'test/actual/with-permalinks/', 63 | src: '!*.*' 64 | }, 65 | 66 | "with-list-of-languages": { 67 | options: { 68 | i18n: { 69 | languages: ["en", "fr", "es"], 70 | templates: ['test/fixtures/templates/*.hbs'] 71 | } 72 | }, 73 | dest: 'test/actual/with-list-of-languages/', 74 | src: '!*.*' 75 | } 76 | 77 | }, 78 | 79 | /** 80 | * Run mocha tests. 81 | */ 82 | mochaTest: { 83 | tests: { 84 | options: { 85 | reporter: 'spec' 86 | }, 87 | src: ['test/**/*-test.js'] 88 | } 89 | }, 90 | 91 | // Before creating new files, remove files from previous build. 92 | clean: ['test/actual/**/*.html'] 93 | 94 | }); 95 | 96 | // Load npm plugins to provide necessary tasks. 97 | grunt.loadNpmTasks('grunt-assemble'); 98 | grunt.loadNpmTasks('grunt-contrib-clean'); 99 | grunt.loadNpmTasks('grunt-mocha-test'); 100 | 101 | grunt.registerTask('test', ['mochaTest']); 102 | 103 | // Default task to be run. 104 | grunt.registerTask('default', ['clean', 'assemble', 'test']); 105 | }; 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # grunt-assemble-i18n [![NPM version](https://badge.fury.io/js/grunt-assemble-i18n.svg)](http://badge.fury.io/js/grunt-assemble-i18n) [![Build Status](https://travis-ci.org/assemble/grunt-assemble-i18n.svg)](https://travis-ci.org/assemble/grunt-assemble-i18n) 2 | 3 | > Plugin for adding i18n support to Assemble projects. 4 | 5 | ```sh 6 | $ npm i grunt-assemble-i18n --save 7 | ``` 8 | 9 | ## Other grunt-assemble plugins 10 | 11 | * [grunt-assemble](https://www.npmjs.com/package/grunt-assemble): Static site generator for Grunt.js, Yeoman and Node.js. Used by Zurb Foundation, Zurb Ink, H5BP/Effeckt,… [more](https://www.npmjs.com/package/grunt-assemble) | [homepage](http://assemble.io) 12 | * [grunt-assemble-anchors](https://www.npmjs.com/package/grunt-assemble-anchors): Assemble plugin for creating anchor tags from headings in generated html using Cheerio.js. | [homepage](https://github.com/assemble/grunt-assemble-anchors) 13 | * [grunt-assemble-contextual](https://www.npmjs.com/package/grunt-assemble-contextual): Generates a JSON file with the context of each page. Basic plugin to help see… [more](https://www.npmjs.com/package/grunt-assemble-contextual) | [homepage](https://github.com/assemble/grunt-assemble-contextual) 14 | * [grunt-assemble-decompress](https://www.npmjs.com/package/grunt-assemble-decompress): Assemble plugin for extracting zip, tar and tar.gz archives. | [homepage](https://github.com/assemble/grunt-assemble-decompress) 15 | * [grunt-assemble-download](https://www.npmjs.com/package/grunt-assemble-download): Assemble plugin for downloading files from GitHub. | [homepage](https://github.com/assemble/grunt-assemble-download) 16 | * [grunt-assemble-lunr](https://www.npmjs.com/package/grunt-assemble-lunr): Assemble plugin for adding search capabilities to your static site, with lunr.js. | [homepage](http://assemble.io) 17 | * [grunt-assemble-navigation](https://www.npmjs.com/package/grunt-assemble-navigation): Assemble navigation plugin. Automatically generate Bootstrap-style, multi-level side nav. See the sidenav on assemble.io for… [more](https://www.npmjs.com/package/grunt-assemble-navigation) | [homepage](https://github.com/assemble/grunt-assemble-navigation) 18 | * [grunt-assemble-permalinks](https://www.npmjs.com/package/grunt-assemble-permalinks): Permalinks plugin for Assemble, the static site generator for Grunt.js, Yeoman and Node.js. This plugin… [more](https://www.npmjs.com/package/grunt-assemble-permalinks) | [homepage](https://github.com/assemble/grunt-assemble-permalinks) 19 | * [grunt-assemble-sitemap](https://www.npmjs.com/package/grunt-assemble-sitemap): Sitemap plugin for Assemble | [homepage](http://assemble.io/plugins) 20 | * [grunt-assemble-toc](https://www.npmjs.com/package/grunt-assemble-toc): Assemble middleware for adding a Table of Contents (TOC) to any HTML page. | [homepage](http://assemble.io) 21 | * [grunt-assemble-wordcount](https://www.npmjs.com/package/grunt-assemble-wordcount): Assemble plugin for displaying wordcount and average reading time to blog posts or pages. | [homepage](https://github.com/assemble/grunt-assemble-wordcount) 22 | 23 | ## Contributing 24 | 25 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/assemble/grunt-assemble-i18n/issues/new). 26 | 27 | ## Author 28 | 29 | **Jon Schlinkert** 30 | 31 | + [github/assemble](https://github.com/assemble) 32 | + [twitter/assemble](http://twitter.com/assemble) 33 | 34 | ## License 35 | 36 | Copyright © 2015 Jon Schlinkert 37 | Released under the MIT license. 38 | 39 | *** 40 | 41 | _This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on September 25, 2015._ -------------------------------------------------------------------------------- /test/main-test.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * grunt-assemble-i18n 3 | * 4 | * Copyright (c) 2014-2015, Jon Schlinkert. 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | // Node.js 9 | var path = require('path'); 10 | 11 | // node modules 12 | var expect = require('chai').expect; 13 | var cheerio = require('cheerio'); 14 | var file = require('fs-utils'); 15 | 16 | /** 17 | * Initilize an object of {filename: true} 18 | * pairs used for expect later 19 | * 20 | * @param {[Array]} files - List of base files 21 | * @return {[Object]} - Object of {filename: true} 22 | */ 23 | var initFileList = function (files) { 24 | var list = {}; 25 | files.forEach(function (f) { 26 | list[f.filename] = true; 27 | }); 28 | return list; 29 | }; 30 | 31 | /** 32 | * Validate that each file in the list exists. 33 | * 34 | * @param {[Object]} files - List of base files 35 | * @param {[String]} base - Base path to look for filenames 36 | * @return {[Object]} - Object of {filename: (true|false)} 37 | */ 38 | var validateFileListExists = function (files, base) { 39 | var list = {}; 40 | files.forEach(function (f) { 41 | list[f.filename] = file.exists(base, f.filename); 42 | }); 43 | return list; 44 | }; 45 | 46 | var validateLanguageAttribute = function (files, base) { 47 | for (var i = 0; i < files.length; i++) { 48 | var f = files[i]; 49 | var filepath = path.join(base, f.filename); 50 | var contents = file.readFileSync(filepath); 51 | var $ = cheerio.load(contents); 52 | var actual = $('html[lang="' + f.language + '"]'); 53 | expect(actual.length).to.eql(1); 54 | }; 55 | }; 56 | 57 | var validateLodashYFMContent = function (files, base) { 58 | for (var i = 0; i < files.length; i++) { 59 | var f = files[i]; 60 | var filepath = path.join(base, f.filename); 61 | var contents = file.readFileSync(filepath); 62 | var $ = cheerio.load(contents); 63 | var actual = $('#lodash-parsed'); 64 | var expected = $('title'); 65 | expect(actual.text()).to.eql(expected.text()); 66 | }; 67 | }; 68 | 69 | // tests 70 | describe('assemble-contrib-i18n', function() { 71 | 72 | describe('when no plugin is used', function() { 73 | 74 | // this metadata shows there are some issues 75 | // with the regular data or front-matter 76 | // when adding pages through the pages collection 77 | // on assemble options 78 | var metadata = [ 79 | { filename: 'en.html', language: 'fr' }, 80 | { filename: 'es.html', language: 'fr' }, 81 | { filename: 'fr.html', language: 'fr' }, 82 | { filename: 'index.html', language: 'fr' } 83 | ]; 84 | 85 | it('it should create four files', function() { 86 | var expected = initFileList(metadata); 87 | var actual = validateFileListExists(metadata, 'test/actual/without-plugin'); 88 | expect(actual).to.eql(expected); 89 | }); 90 | 91 | it('it should contain a language attribute on the html tag', function() { 92 | validateLanguageAttribute(metadata, 'test/actual/without-plugin'); 93 | }); 94 | 95 | }); 96 | 97 | describe('when i18n plugin is used', function() { 98 | 99 | var metadata = [ 100 | { filename: 'index-en.html', language: 'en' }, 101 | { filename: 'index-es.html', language: 'es' }, 102 | { filename: 'index-fr.html', language: 'fr' } 103 | ]; 104 | 105 | it('it should create three index-{lang}.html files', function() { 106 | var expected = initFileList(metadata); 107 | var actual = validateFileListExists(metadata, 'test/actual/with-plugin'); 108 | expect(actual).to.eql(expected); 109 | }); 110 | 111 | it('it should contain a language attribute on the html tag', function () { 112 | validateLanguageAttribute(metadata, 'test/actual/with-plugin'); 113 | }); 114 | 115 | it('with data it should contain language-specific lodash parsed string', function() { 116 | validateLodashYFMContent(metadata, 'test/actual/with-plugin'); 117 | }); 118 | 119 | }); 120 | 121 | describe('when i18n and permalinks plugins are used', function() { 122 | 123 | var metadata = [ 124 | { filename: 'en/index.html', language: 'en' }, 125 | { filename: 'es/index.html', language: 'es' }, 126 | { filename: 'fr/index.html', language: 'fr' } 127 | ]; 128 | 129 | it('it should create three {lang}/index.html files', function() { 130 | var expected = initFileList(metadata); 131 | var actual = validateFileListExists(metadata, 'test/actual/with-permalinks'); 132 | expect(actual).to.eql(expected); 133 | }); 134 | 135 | it('it should contain a language attribute on the html tag', function () { 136 | validateLanguageAttribute(metadata, 'test/actual/with-permalinks'); 137 | }); 138 | 139 | }); 140 | 141 | describe('when i18n plugin is used with a list of languages', function() { 142 | 143 | var metadata = [ 144 | { filename: 'index-en.html', language: 'en' }, 145 | { filename: 'index-es.html', language: 'es' }, 146 | { filename: 'index-fr.html', language: 'fr' } 147 | ]; 148 | 149 | it('it should create three index-{lang}.html files', function() { 150 | var expected = initFileList(metadata); 151 | var actual = validateFileListExists(metadata, 'test/actual/with-plugin'); 152 | expect(actual).to.eql(expected); 153 | }); 154 | 155 | it('it should contain a language attibute on the html tag', function () { 156 | validateLanguageAttribute(metadata, 'test/actual/with-plugin'); 157 | }); 158 | 159 | }); 160 | }); 161 | --------------------------------------------------------------------------------