Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request feature: add internationalization(i18n) support on server and client side #571

Open
ghost opened this issue Sep 20, 2014 · 17 comments

Comments

@ghost
Copy link

ghost commented Sep 20, 2014

Right now I'm struggling with this approach. I want to know what are thought about this approach from contributors and users that know something about it. Or I'll take other better suggestions about implementing i18n support in Angular and Node + Express engine.

@JaKXz JaKXz added the question label Sep 25, 2014
@azachar
Copy link

azachar commented Sep 28, 2014

Hmm, interesting... how about to integrate https://angular-gettext.rocketeer.be/ instead? It would work just in Angular, but I guess that is all you need.

@etiennetremel
Copy link

I would suggest using Angular Translate instead. Here is how I deal with translation for the Frontend part:

  1. Install Bower dependencies:

    bower install -S angular-translate

    bower install -S angular-translate-loader-static-files

    bower install -S angular-translate-loader-partial

  2. Create a i18n folder in your client directory: /client/i18n

  3. Configure Angular Translate in /client/app/app.js:

    angular.module('myApp', [
      // ...
      'pascalprecht.translate'
    ])
    
    .config(['$translateProvider', function ($translateProvider) {
    
      // Configure Angular Translate
      $translateProvider.useLoader('$translatePartialLoader', {
        urlTemplate: 'i18n/{part}/{lang}.json'
      });
    
      // Set default translation
      $translateProvider.preferredLanguage('en_US');
    
    }])
    
    
  4. Create a RequireTranslations Service

    // Require translations
    .factory('RequireTranslations', ['$translatePartialLoader', '$translate', function ($translatePartialLoader, $translate) {
      return function () {
        // Add Global translation
        $translatePartialLoader.addPart('app');
    
        // Add partials
        angular.forEach(arguments, function (translationKey) {
          $translatePartialLoader.addPart(translationKey);
        });
        return $translate.refresh();
      }
    }])
    
  5. For each routes, add a directory into i18n with corresponding translation file as follow:
    Angular application:

    |- client
    |  |- app
    |  |  |- page
    |  |  |  |- home
    |  |  |  |  |- home.controller.js
    |  |  |  |  |- home.html
    |  |  |  |  |- home.scss
    |  |  |  |- about
    |  |  |  |  |- about.controller.js
    |  |  |  |  |- about.html
    |  |  |  |  |- about.scss
    |  |  |  |- page.js
    

    Corresponding Translation:

    |- client
    |  |- i18n
    |  |  |- app                // Global translation, used on every routes
    |  |  |  |- en_US.json
    |  |  |  |- fr_FR.json
    |  |  |- page               // Specific translation only loaded if loading the corresponding template
    |  |  |  |- home
    |  |  |  |  |- en_US.json
    |  |  |  |  |- fr_FR.json
    |  |  |  |- about
    |  |  |  |  |- en_US.json
    |  |  |  |  |- fr_FR.json
    
  6. Then, for each route, resolve the translation file /client/app/page/page.js:

    .config(function ($stateProvider) {
      $stateProvider
        .state('app.home', {
          url: '/',
          templateUrl: 'app/page/home/home.html',
          controller: 'HomeCtrl',
          resolve: {
            translation: function(RequireTranslations) {
              return RequireTranslations('page/home');
            }
          }
        })
        .state('app.about', {
          url: '/about',
          templateUrl: 'app/page/about/about.html',
          controller: 'AboutCtrl',
          resolve: {
            translation: function(RequireTranslations) {
              return RequireTranslations('page/about');
            }
          }
        });
    })
    
  7. To switch between languages, in your nav bar controller you can mix this code with a ng-click:

    $scope.changeLanguage = function (key) {
      $translate.use(key);
    };
    

Hope this can help.

@JaKXz JaKXz added the info label Oct 7, 2014
@azachar
Copy link

azachar commented Oct 7, 2014

I do not like Angular Translate.

Angular-gettext let's you focus on developing your application. Just write your code ... No need to maintain translation keys or magic values, that just causes headaches!

@fiznool
Copy link

fiznool commented Oct 13, 2014

+1 for angular-gettext. Much easier to work with.

@dmarcelino
Copy link

+1 for angular-gettext. I haven't tried Angular Translate but I can say angular-gettext is easy to setup and simple to use.

@Awk34
Copy link
Member

Awk34 commented Nov 14, 2014

Anyone know if there are any significant performance differences between them?

@azachar
Copy link

azachar commented Nov 15, 2014

Well, angular gettext is quite fast so far, but it is just my personal experience, no real hard data to compare, if you want look for example at www.slacklinefestivals.com, so far it was translated into 9 languages and it works quite nice :)

What I like the most is that you do not think in KEY=VALUE paradigm. You just focus on your html in English and all your keys are extracted from your current text that is actually the key.

@Awk34 Awk34 added this to the 2.4.0 milestone Jul 16, 2015
@imcoddy
Copy link

imcoddy commented Jul 23, 2015

Looks like many people prefer angular-gettext.
Can anyone provide some step-by-step guidance like @etiennetremel did? It would help a lot for someone who come to this issue and can find a solution quickly.

@arryon
Copy link

arryon commented Apr 3, 2017

Bumping this thread. angular-gettext seems like the perfect solution for integration with this generator. However, its module definition looks pretty outdated, not giving default exports etc.
Has anyone got gettext working with this generator? An example would be very helpful.

@arryon
Copy link

arryon commented Apr 3, 2017

As it so happens, I've solved integrating gettext. See instructions below.

I use Webpack 1.12 with a modified version of the generator (manually updated packages), angular v1.6.2, npm v6.9.1, angular-gettext v2.3.9, and gulp-angular-gettext v2.2.0. Your mileage may vary. Also, Webpack 2 has built-in support voor json files, so no need to install the loader in that case.

First, for Webpack < 2, add the json-loader , npm install --save-dev json-loader, and edit webpack.make.js, L129:

    // Initialize module
    config.module = {
        noParse: [/html2canvas/, /pdfmake/],
        rules: [{
            test: /\.json$/,
            use: 'json-loader'
        }],

Second, install angular-gettext, npm install --save angular-gettext and the gulp plugin, npm install --save-dev gulp-angular-gettext.
Edit your gulpfile:

//add the plugin to our imports
import gettext from 'gulp-angular-gettext';

//add two tasks: extracting and compiling .po files
gulp.task('translate:extract', () => {
    return gulp.src(paths.client.views)
        .pipe(gettext.extract('template.pot', {
            // options to pass to angular-gettext-tools...
        }))
        .pipe(gulp.dest('po/'));
});

gulp.task('translate:compile', () => {
    return gulp.src('po/**/*.po')
        .pipe(gettext.compile({
            // options to pass to angular-gettext-tools...
            format: 'json',
        }))
        .pipe(gulp.dest(`${clientPath}/components/translations/`));
});

I use format 'json' because this produces json files that I can import in my own angular module, since gulp-angular-gettext produces a plain javascript module that I don't find very re-usable.
You can decide where you want the translation to be injected. To use it when developing, add it to your serve task for instance. Whenever you want to update the translations, extract and re-compile them in a separate terminal window, and your dev server should automatically reload with the updates.

Then, in ${clientPath}/components/translations, add a new module translations.module.ts:

'use strict';
const angular = require('angular');

const json = require('json-loader!./nl.json');

function transConfig(appConfig, gettextCatalog) {
  'ngInject';
  gettextCatalog.setStrings('nl',json.nl);
  gettextCatalog.setCurrentLanguage(appConfig.defaultLocale);
  gettextCatalog.debug = true;
}

export default angular.module('myAppName.translations', [])
  .run(transConfig)
  .name;

Finally In ${clientPath}/app.ts, import and declare gettext along with your module like this:

// import statement
import 'angular-gettext';
import translations from '../components/translations/translations.module';

angular.module('myAppName', [
  // ...other imports
  'gettext',
  translations,
])
// ...rest of the main app definitions

After this, your module will take care of translation for you :).

@stherrienaspnet
Copy link
Collaborator

stherrienaspnet commented Apr 3, 2017 via email

@arryon
Copy link

arryon commented Apr 5, 2017

Then I regret that the team has chosen angular-translate as translation library. I've worked with both, and the biggest advantage of gettext is its approach in using industry standard translation tools. angular-translate is just a loader of JSON files with some directives, whereas gettext can use every PO editor available, even to offload translation to a third party. Also, the asynchronous nature of angular-translate adds unneeded complexity to your Angular app.

In any case, I hope my contribution will be useful for anyone wanting to add gettext to the generator.

@stherrienaspnet
Copy link
Collaborator

Hello @arryon, unfortunately when selecting the support solution for internationalization I did not know angular-gettext. Knowing the popularity of angular-translate and our experience of using with this library my choice stopped on this one. I recently looked at angular-gettext and I can confess that this library looks really good. All the work to fit the generator and its pages and modules has already been done, this is bringing at least one i18n option for for the users. You are welcome to make the required changes to the generator and we will replace angular-translate by angular-gettext. I will provide you the changeset number to look for and it will be easy to see the changes I have made to the generator.

@arryon
Copy link

arryon commented Apr 5, 2017

I will happily give it a try :). Contributing to the generator would be a good option since I've made heavy use of it in the previous years.

@stherrienaspnet
Copy link
Collaborator

@arryon you can follow the pull request i just made this morning :)
#2534

@stherrienaspnet
Copy link
Collaborator

Hello @arryon, following recent discussion with the development team it was decided that we will stay with angular-translate for version 4.x. But other users can already beneficiate from the information you provided to integrate gettext with the generator :)

@arryon
Copy link

arryon commented Apr 7, 2017

@stherrienaspnet Thanks for the heads-up! I believe the additional work to add a second translator will be much less now at least one is implemented :)

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

No branches or pull requests

9 participants