0

I have read lots of information on SO that I can't have $http call inside config but what I can do is create own provider and use this provider inside a config.

But none of the topics I read show how to actually use the information gathered in API call in provider inside a config().

So the provider I created is this:

(function () {
    'use strict';

    angular
        .module('app', [])
        .provider('translateOwnProvider', Provider);

    function Provider () {
        this.$get = function($http) {

            $http({
                url: 'http://ipinfo.io/json',
                method: 'GET'
            })
            .then(function(response) {
                var homeCountry = response.data.country;
                var homeCountryLower = homeCountry.toLowerCase();
                console.log(response.data);
            }, function(errorCall) {
                console.log("error");
            });

            return homeCountryLower;
            // ?????
        };
    };

})();

So in line 23 (bottom of script) I return value, I don't know if it's actually a good way to do this, it's the first time I have tried this and need your help guys.

Next in config file named really common app.js I have config with

  • routing
  • setting a lenguage of user

the code is:

(function () {
    'use strict';

    angular
        .module('app', [
            'ngRoute',
            'pascalprecht.translate'
        ])
        .config(config);

    //$inject for minify issue
    config.$inject = ['$routeProvider', '$translateProvider', 'translateOwnProvider'];

    function config ($routeProvider, $translateProvider, translateOwnProvider) {
        $routeProvider
            .when('/', {
                controller: 'mainCtrl',
                templateUrl: 'views/main.html'
            })
            .otherwise('/');

        // add translation tables
         $translateProvider.translations('en', translationsEN);
         $translateProvider.translations('de', translationsDE);
         $translateProvider.translations('pl', translationsPL);

         // preferredLanguage is gather should be gather in provider
         $translateProvider.preferredLanguage('en');

         $translateProvider.fallbackLanguage('en');
         //fallbackLanguage in case somebody hides his IP
    };


})();

In line 28 I set a preferredLenguage and I want this to be a value returned in own provider: homeCountryLower.

At the moment I don't have any error in console but this doesn't work obviously and page doesn't load at all, it stays blank.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
BT101
  • 3,666
  • 10
  • 41
  • 90
  • *But none of the topics I read show how to actually use the information gathered in API call in provider inside a config()* - because you can't. Even if you could, this would create race condition because HTTP request is asynchronous. – Estus Flask Aug 28 '17 at 15:10
  • So there is no solution to set preffered user lenguage basing on user IP? – BT101 Aug 28 '17 at 15:16
  • Use route resolver, as the answer suggests. – Estus Flask Aug 28 '17 at 15:26
  • And I will be able to use gathered information in route `resolve: gatherApi: function { $http.get }` information inside this config where routes are present? – BT101 Aug 28 '17 at 15:31
  • You will be able to use information inside route controller/component, according to how resolvers work. – Estus Flask Aug 28 '17 at 15:33
  • So I'm up to conclusion that it is impossible to set (angular-tranlate module https://github.com/angular-translate/angular-translate) `prefferedLanguage` basing on IP since setting this variable is only possible in provider and to get IP I need `$http` call which is not achievable at this stage. I will need to create own translate service or a factory. Am I right? – BT101 Aug 28 '17 at 15:38
  • In `config` you already have the reference to `$translateProvider` and can use it inside a resolver, like `$http(..).then(function (result) { $translateProvider... })`. Since this is a hack that breaks expected precedence, the fact if it works or not depends on how $translate works internally. – Estus Flask Aug 28 '17 at 16:08

2 Answers2

1

I would suggest you to put the api call into resolve something like this. This would ensure your app/main controller is not instantiated until the service call is done with.

resolve: {
    translateService: function($http, $route){
      return $http.get('http://ipinfo.io/json')
      .then(function(response){
        return response.data;
      })
    }
}

Now you can inject the translateService in your controller and set it in a factory/service, which you can re-use across the application as it being singleton in nature.

Thalaivar
  • 23,282
  • 5
  • 60
  • 71
  • But I do not use any own service or factory and controller to get translate done. I just set the language on the first app run and language tables which I add in index.html by ``. This tables look like this: https://gist.github.com/anonymous/8307d8f41acb1ebe638aa506ca338af7. The translation is done by this module: https://angular-translate.github.io/docs/#/guide/00_installation – BT101 Aug 28 '17 at 15:06
  • Why do you need a provider here translateOwnProvider unless you are going to set something by defualt so that translateService later when used across the application will have this preference. Why not resolve? – Thalaivar Aug 28 '17 at 15:07
  • I need this provider because I want to set prefferedLenguage to english when somebody came from England IP or polish when somebody came from Poland IP and I also use `fallbackLanguage` if somebody came from for example some country from Africa that my app doesn't handle. – BT101 Aug 28 '17 at 15:11
  • Why can't you do that in controller by setting if the user is coming from england or polish in your mainCtrl after your manCtrl resolve returns the ip address from "url: 'http://ipinfo.io/json'," – Thalaivar Aug 28 '17 at 15:15
  • I can not because module which is use (angular-translate) set the `$translateProvider.preferredLanguage('en');` in, as you can see, in provider which I can not use inside the controller because it is a provider. In other words this: `app.controller('myCtrl', function($anyProvider)` will not work. – BT101 Aug 28 '17 at 15:18
  • And also while creating a provider use like below: ngular .module('app', []) .provider('translateown', translateownProvider); as translateOwn can be injected in controller as a service. – Thalaivar Aug 28 '17 at 15:40
  • Below is a fiddle where i copied your provider and intergated in a sample code... https://codepen.io/anon/pen/VzErGM (updated code-pen) – Thalaivar Aug 28 '17 at 15:40
  • `/* From the 16th line change the language and check the translate filter */` how to do so? I tried `$translateProvider.preferredLanguage('de');` and `translateownProvider.preferredLanguage('de');` with no luck.. I placed it at line 16 as you wrote there. I aslo tried `translateown.preferredLanguage('de');`. – BT101 Aug 28 '17 at 16:01
0

I finished with conclusion that it is not possible to use gathered info from backend call in config(). Maybe it is possible to use some kind of hack with resolve function but I couldn't figure it out.

What I did instead of this call is I used window.navigator.language in my config() so now my translation script is not based on user IP but it's based on user browser language. It's not as satisfying as IP because I still can have user which is from Poland and has browser set to english and then my page will display in english.

I could also write own service which would translate page for me but I really wanted to use angular-translate module: link to module.

Note that I used window.navigator.language not a $window because this second one is not achievable in config() as well. So my solution may cause some problems during testing.

I wrote this for anyone who will came into this topic in future.

BT101
  • 3,666
  • 10
  • 41
  • 90