Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localize URL's with ui-router and angular-translate

I am using ui-router for routing and angular-translate for translations. What i would like to achieve is having the selected language bind to the url like so:

www.mydomain.com/en/ www.mydomain.com/ru/ www.mydomain.com/en/about www.mydomain.com/ru/about 

and it will respond accordingly.

Tried to look for examples, but did not find anything. If someone implemented similar solution, i would love to hear how you did it.

Thanks

like image 725
Leon Avatar asked Jun 18 '14 09:06

Leon


2 Answers

I use something along these lines:

CoffeeScript

angular.module('app') .config([   '$stateProvider'   ($stateProvider) ->     $stateProvider.state 'app',       abstract: true       url: '/{locale}'     $stateProvider.state 'app.root',       url: ''     $stateProvider.state 'app.root.about',       url: '/about' ]) 

JavaScript

angular.module('app').config([   '$stateProvider', function($stateProvider) {     $stateProvider.state('app', {       abstract: true,       url: '/{locale}'     });     $stateProvider.state('app.root', {       url: ''     });     return $stateProvider.state('app.root.about', {       url: '/about'     });   } ]); 

With this, you can inject $stateParams into your controller and get access to the locale there:

CoffeeScript

angular.module('app') .controller('appCtrl', [   '$scope', '$stateParams'   ($scope, $stateParams) ->     $scope.locale = $stateParams.locale ]) 

JavaScript

angular.module('app').controller('appCtrl', [   '$scope', '$stateParams', function($scope, $stateParams) {     return $scope.locale = $stateParams.locale;   } ]); 

Or, if you want to affect the whole page automatically, use the $stateChangeStart event in an application controller or similar:

CoffeeScript

$scope.$on '$stateChangeStart', (event, toState, toParams, fromState, fromParams) ->   $translate.use(toParams.locale) 

JavaScript

$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {   $translate.use(toParams.locale); }); 

Note that if you're using angular-translate v1.x you should use $translate.uses instead of $translate.use.

like image 170
mjtko Avatar answered Sep 28 '22 00:09

mjtko


The solution is valid only if you want to have URLs of the below format:

domain.com/{locale}/about

hence:

domain.com/en/about domain.com/mt/about

Recently we were required to implement translations for the full URL, therefore:

domain.com/{locale}/{about}

where {about} is translated in the respective language:

domain.com/en/about domain.com/mt/fuqna

I don't know if the below approach is the best one, however it does work.

For starters, the first difference is that we set up ui-router states to be generated dynamically using a service which retrieves the routes from a JSON file. This is done similarly to @ChrisT's answer in: Angular - UI Router - programmatically add states

module.service("routingService", ["$http", function($http) {      self.get = function(options) {                    return self.getByLocale({             market: options.urlMarketCode         });     };      self.getByLocale = function(options) {         var market = options.market;          // loads the different .json files based on the different market values passed, ex: routes-en.json         var configurationKey = "routes-" + market;          return $http({             method: "GET",             url: configurationKey + ".json",             headers: {                 "Content-Type": "application/json"             }         }).then(function(response) {             if (response.data) {                 return response.data;             }             return undefined;         }).catch(function(e) {             console.log(e);         });     };      return self; }]); 

We would then consume the above routingService in the run block of the application:

// run the module and register the state change handler angular.module("sportsbook-app").run(["$state", "$rootScope", "routingService", "stateService",     function ($state, $rootScope, routingService, stateService) {         // retrieve the routing heirarchy from file         routingService.get({             urlMarketCode: $rootScope.language         }).then(function (response) {             if (response) {                 // add the routes to the $stateProvider                 stateService.generate(response);             }         });     } ]); 

And finally the stateService simply parses the JSON file and creates the routing hierarchy using ChrisT's runtimeStates.addState.

I will try to include a working demo in the near future.

Credits also go to @karl-agius.

like image 22
Kevin Farrugia Avatar answered Sep 28 '22 00:09

Kevin Farrugia