View on GitHub

translate-compile

angular-translate angular pre-compiler markup translate-compile grunt plugin

Download this project as a .zip file Download this project as a tar.gz file

grunt-translate-compile

A pre-compiler for angular-translate based on TL: a simple write-less markup specially designed for angular-translate.

1. Translation Markup - TL

The translation markup intends to drastically reduce the amount of typing needed to translate your app, by keeping it simpler and improving it's maintenance.

Briefing: A translation file begins with the declaration of all supported languages of your application. A custom numeric code (key) must be assigned to each one of the declared languages. In the sample that comes next, we're saying that [american english code is 1], [brazilian portuguese is 2] and [spanish from spain is 3]. Translation values are assigned directly to the language key.

Tabs must be used for indentation. Spaces are not yet allowed. Indentation must be respected to avoid unwanted results.

1.1 - Hello World from TL

LANGUAGES
  1:english
  2:deutsch

HELLO
  WORLD
    1:Hello World
    2:Hallo Welt
Charcount 83

Compiled:

var angTranslations = {
  "english": {
    "HELLO": {
      "WORLD": "Hello World"
    }
  },
  "deutsch": {
    "HELLO": {
      "WORLD": "Hallo Welt"
    }
  }
};
Charcount 164

1.2 - Type translations keys only once for all your languages

LANGUAGES
  1:english
  2:deutsch
  3:spanish
  4:portuguese

UNITED_STATES
  NAME
    1:United States
    2:Vereinigte Staaten
    3,4:Estados Unidos
  LANGUAGE
    1:English
    2:Englisch
    3:Inglés
    4:Inglês
SPAIN
  NAME
    1:Spain
    2:Spanien
    3:España
    4:Espanha
  LANGUAGE
    1:Spanish
    2:Spanisch
    3:Español
    4:Espanhol
BRAZIL
  NAME
    1:Brazil
    2:Brasilien
    3,4:Brasil
  LANGUAGE
    1:Portuguese
    2:Portugiesisch
    3:Portugués
    4:Português
Charcount 489

Compiled:

var angTranslations = {
  "english": {
    "UNITED_STATES": {
      "NAME": "United States",
      "LANGUAGE": "English"
    },
    "SPAIN": {
      "NAME": "Spain",
      "LANGUAGE": "Spanish"
    },
    "BRAZIL": {
      "NAME": "Brazil",
      "LANGUAGE": "Portuguese"
    }
  },
  "deutsch": {
    "UNITED_STATES": {
      "NAME": "Vereinigte Staaten",
      "LANGUAGE": "Englisch"
    },
    "SPAIN": {
      "NAME": "Spanien",
      "LANGUAGE": "Spanisch"
    },
    "BRAZIL": {
      "NAME": "Brasilien",
      "LANGUAGE": "Portugiesisch"
    }
  },
  "spanish": {
    "UNITED_STATES": {
      "NAME": "Estados Unidos",
      "LANGUAGE": "Inglés"
    },
    "SPAIN": {
      "NAME": "España",
      "LANGUAGE": "Español"
    },
    "BRAZIL": {
      "NAME": "Brasil",
      "LANGUAGE": "Portugués"
    }
  },
  "portuguese": {
    "UNITED_STATES": {
      "NAME": "Estados Unidos",
      "LANGUAGE": "Inglês"
    },
    "SPAIN": {
      "NAME": "Espanha",
      "LANGUAGE": "Espanhol"
    },
    "BRAZIL": {
      "NAME": "Brasil",
      "LANGUAGE": "Português"
    }
  }
};
Charcount 1081

Notice how the writing was significantly reduced as it's no longer needed to rewrite every key for each language, we are also skipping blocks and quotes. Thus we can focus on what really matters: the translations. Maintenance is also greatly improved, as adding a new key will no longer be a hunt for the right spot of each language.

1.3 - Type repeated translation values only once too

LANGUAGES
  1:enUS
  2:ptBR
  3:esES

CREDIT_CARD
  NAME
    1:Credit Card
    2:Cartão de Crédito
    3:Tarjeta de Crédito
  FLAG
    VISA
      1,2,3:Visa
    MASTERCARD
      1,2,3:Mastercard
    AMEX
      1,2,3:American Express
    DINERS
      1,2,3:Diners
Charcount 262

Compiled:

var angTranslations = {
  "enUS": {
    "CREDIT_CARD": {
      "NAME": "Credit Card",
      "FLAG": {
        "VISA": "Visa",
        "MASTERCARD": "Mastercard",
        "AMEX": "American Express",
        "DINERS": "Diners"
      }
    }
  },
  "ptBR": {
    "CREDIT_CARD": {
      "NAME": "Cartão de Crédito",
      "FLAG": {
        "VISA": "Visa",
        "MASTERCARD": "Mastercard",
        "AMEX": "American Express",
        "DINERS": "Diners"
      }
    }
  },
  "esES": {
    "CREDIT_CARD": {
      "NAME": "Tarjeta de Crédito",
      "FLAG": {
        "VISA": "Visa",
        "MASTERCARD": "Mastercard",
        "AMEX": "American Express",
        "DINERS": "Diners"
      }
    }
  }
};
Charcount 698

1.4 - Organize your translations into multiple files

Although we recommend you to include language declarations in all your translation files, they are only required in the first read translation file. Language declarations will often serve you as legend for language keys/values.

File 1: menu.tl

LANGUAGES
  1:enUs
  2:ptBr
  3:esEs

MENU
  CART
    EMPTY
      1:Empty Cart
      2:Esvaziar Carrinho
      3:Vaciar Carrito
    CHECKOUT
      1:Checkout
      2:Fechar Pedido
      3:Realizar Pedido
  USER
    LABEL
      1:User
      2:Usuário
      3:Usuario
    DROPDOWN
      EDIT
        1:Edit
        2,3:Editar
      LOGOUT
        1:Logout
        2:Sair
        3:Finalizar la Sesión
Charcount 398

File 2: country.tl

LANGUAGES
  1:enUs
  2:ptBr
  3:esEs

COUNTRY
  USA
    NAME
      1:United States
      2,3:Estados Unidos
    LANGUAGE
      1:English
      2:Inglês
      3:Inglés
  BRAZIL
    NAME
      1:Brazil
      2,3:Brasil
    LANGUAGE
      1:Portuguese
      2:Português
      3:Portugués
  SPAIN
    NAME
      1:Spain
      2:Espanha
      3:España
    LANGUAGE
      1:Spanish
      2:Espanhol
      3:Español
Charcount 408

File 3: us-states.tl

LANGUAGES
  1:enUs
  2:ptBr
  3:esEs

COUNTRY
  USA
    STATES
      CALIFORNIA
        NAME
          1,3:California
          2:Califórnia
        ACRONYM
          1,2,3:CA
      NEW_YORK
        NAME
          1:New York
          2:Nova Iorque
          3:Nueva York
        ACRONYM
          1,2,3:NY
      NORTH_CAROLINA
        NAME
          1:North Carolina
          2:Carolina Do Norte
          3:Carolina del Norte
        ACRONYM
          1,2,3:NC
Charcount 463

Compiled Result:

var angTranslations = {
  "enUs": {
    "COUNTRY": {
      "USA": {
        "NAME": "United States",
        "LANGUAGE": "English",
        "STATES": {
          "CALIFORNIA": {
            "NAME": "California",
            "ACRONYM": "CA"
          },
          "NEW_YORK": {
            "NAME": "New York",
            "ACRONYM": "NY"
          },
          "NORTH_CAROLINA": {
            "NAME": "North Carolina",
            "ACRONYM": "NC"
          }
        }
      },
      "BRAZIL": {
        "NAME": "Brazil",
        "LANGUAGE": "Portuguese"
      },
      "SPAIN": {
        "NAME": "Spain",
        "LANGUAGE": "Spanish"
      }
    },
    "MENU": {
      "CART": {
        "EMPTY": "Empty Cart",
        "CHECKOUT": "Checkout"
      },
      "USER": {
        "LABEL": "User",
        "DROPDOWN": {
          "EDIT": "Edit",
          "LOGOUT": "Logout"
        }
      }
    }
  },
  "ptBr": {
    "COUNTRY": {
      "USA": {
        "NAME": "Estados Unidos",
        "LANGUAGE": "Inglês",
        "STATES": {
          "CALIFORNIA": {
            "NAME": "Califórnia",
            "ACRONYM": "CA"
          },
          "NEW_YORK": {
            "NAME": "Nova Iorque",
            "ACRONYM": "NY"
          },
          "NORTH_CAROLINA": {
            "NAME": "Carolina Do Norte",
            "ACRONYM": "NC"
          }
        }
      },
      "BRAZIL": {
        "NAME": "Brasil",
        "LANGUAGE": "Português"
      },
      "SPAIN": {
        "NAME": "Espanha",
        "LANGUAGE": "Espanhol"
      }
    },
    "MENU": {
      "CART": {
        "EMPTY": "Esvaziar Carrinho",
        "CHECKOUT": "Fechar Pedido"
      },
      "USER": {
        "LABEL": "Usuário",
        "DROPDOWN": {
          "EDIT": "Editar",
          "LOGOUT": "Sair"
        }
      }
    }
  },
  "esEs": {
    "COUNTRY": {
      "USA": {
        "NAME": "Estados Unidos",
        "LANGUAGE": "Inglés",
        "STATES": {
          "CALIFORNIA": {
            "NAME": "California",
            "ACRONYM": "CA"
          },
          "NEW_YORK": {
            "NAME": "Nueva York",
            "ACRONYM": "NY"
          },
          "NORTH_CAROLINA": {
            "NAME": "Carolina del Norte",
            "ACRONYM": "NC"
          }
        }
      },
      "BRAZIL": {
        "NAME": "Brasil",
        "LANGUAGE": "Portugués"
      },
      "SPAIN": {
        "NAME": "España",
        "LANGUAGE": "Español"
      }
    },
    "MENU": {
      "CART": {
        "EMPTY": "Vaciar Carrito",
        "CHECKOUT": "Realizar Pedido"
      },
      "USER": {
        "LABEL": "Usuario",
        "DROPDOWN": {
          "EDIT": "Editar",
          "LOGOUT": "Finalizar la Sesión"
        }
      }
    }
  }
};
Charcount 2705

2. Grunt Plugin

2.1 - Getting Started

This plugin requires Grunt ~0.4.5

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install grunt-translate-compile --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

grunt.loadNpmTasks('grunt-translate-compile');

2.2 - The "translate_compile" task - Overview

1. Add the task

In your project's Gruntfile, add a section named translate_compile to the data object passed into grunt.initConfig().

grunt.initConfig({
  translate_compile: {
    compile: {
      options: {
        // task-specific options go here. refer to options topic
      },
      files: {
        // post-compiling file to the left, pre-compiling files to the right
        'compiled-translations.js': ['translations/*.tl']
      }
    }
  }
});

2. Let your server know about it

Remember to include "translate_compile" inside your server task so the compilation takes place when you start it (connect/express). Something like:

grunt.registerTask('serve', function (target) {
    grunt.task.run([
      'clean:server',
      'translate_compile:compile', // <-- here it is
      'bowerInstall',
      'concurrent:server',
      'autoprefixer',
      'connect:livereload',
      'watch'
    ]);
  });

3. Watch it

For a better experience, watch for any changes made to your translation files (requires grunt-contrib-watch). Something like:

watch: {
  tl: {
    files: ['translations/*.tl'],
    tasks: ['translate_compile:compile'],
    options: {
      livereload: true
    }
  }
},

4. Take to your build

Add the "translate_compile" to your build task. Something like:

grunt.registerTask('build', [
    'clean:dist'
    'bowerInstall',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngmin',
    'translate_compile:compile', // <-- here it is
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'rev',
    'usemin',
    'htmlmin'
  ]);

You should now be good to go!

2.3 - Options

options.translationVar

Type: String Default value: 'angTranslations'

Determines the name of the compiled variable. Ex: var angTranslations = {"usEn":{...}}

options.multipleObjects

Type: Boolean Default value: false

If multipleObjects is set to true there will no longer be only one root variable like angTranslations. Translations will now be splitted into one object per language. Ex: var enUs = {...}; var ptBr = {...}; var esEs = {...}; Variable names will the ones declared in the LANGUAGES section.

options.asJson

Type: Boolean Default value: false

Should this value be set to true there will be no variable assignment inside the file, only the resulting json will be there.

3. Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.

4. Release History

(Nothing yet)