web-dev-qa-db-fra.com

Localisez les URL avec ui-router et angular-translate

J'utilise ui-router pour le routage et angular-translate pour les traductions. Ce que je voudrais réaliser, c'est que la langue sélectionnée soit liée à l'URL comme ceci:

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

et il répondra en conséquence.

J'ai essayé de chercher des exemples, mais je n'ai rien trouvé. Si quelqu'un implémentait une solution similaire, j'aimerais savoir comment vous l'avez fait.

Merci

26
Leon

J'utilise quelque chose dans ce sens:

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'
    });
  }
]);

Avec cela, vous pouvez injecter $stateParams dans votre contrôleur et accédez-y aux paramètres régionaux:

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;
  }
]);

Ou, si vous souhaitez affecter automatiquement la page entière, utilisez le $stateChangeStart événement dans un contrôleur d'application ou similaire:

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);
});

Notez que si vous utilisez angular-translate v1.x, vous devez utiliser $translate.uses au lieu de $translate.use.

30
mjtko

La solution n'est valide que si vous souhaitez avoir des URL du format ci-dessous:

domain.com/{locale}/about

par conséquent:

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

Récemment, nous avons dû implémenter des traductions pour l'URL complète, donc:

domain.com/{locale}/{about}

{about} est traduit dans la langue respective:

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

Je ne sais pas si l'approche ci-dessous est la meilleure, mais elle fonctionne.

Pour commencer, la première différence est que nous configurons des états ui-router à générer dynamiquement à l'aide d'un service qui récupère les routes à partir d'un fichier JSON. Cela se fait de la même manière que la réponse de @ ChrisT dans: Angular - UI Router - programmically 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;
}]);

Nous consommerions alors le routingService ci-dessus dans le bloc run de l'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);
            }
        });
    }
]);

Enfin, le stateService analyse simplement le fichier JSON et crée la hiérarchie de routage à l'aide de runtimeStates.addState de ChrisT.

J'essaierai d'inclure une démonstration de travail dans un avenir proche.

Les crédits vont également à @ karl-agius.

4
Kevin Farrugia

J'ai écrit un article de blog sur la question exacte: http://fadeit.dk/post/angular-translate-ui-router-seo

2
ozooner

Pour les personnes qui souhaitent inclure l'URL à l'aide de ngRoute (je suis venu ici pour rechercher exactement cela), je l'ai implémenté comme suit.

(1) Dans mon .htaccess J'ai récupéré toutes les URL sans sous-domaine de langue et l'ai redirigé vers la valeur par défaut (fr dans mon cas). Le seul véritable inconvénient est que je dois spécifier chaque langue manuellement.

# https://stackoverflow.com/questions/19570572/htaccess-multi-language-site-with-sub-directories-and-default-301/19902914#19902914
# Add language to URL - redirect to default if missing    

RewriteBase /   

# empty url -> redirect to nl/
RewriteCond %{QUERY_STRING} !lang=(nl|fr)
RewriteRule ^$ fr/ [R=301,L]

# url is ONLY '/nl' or '/fr' -> redirect to /nl/ or /fr/ (adding slash)
RewriteRule ^(nl|fr)$  $1/ [R=301,L]

# now all urls have nl/ fr/ -> parse them
RewriteRule ^(nl|fr)/(.*)$  $2?lang=$1&%{query_STRING} [L]

(2) Dans mon bloc Angular du projet config, j'ai simplement analysé l'URL pour obtenir la langue actuelle.

config.$inject = ['$translateProvider', '$windowProvider'];

function config($translateProvider, $windowProvider) {

    var $window,
        language;

        $window  = $windowProvider.$get();
        language = $window.location.pathname.replace(/\//g, '');

    //////

    $translateProvider
      .useStaticFilesLoader({
        prefix: 'translations/',
        suffix: '.json'
          })
      .useSanitizeValueStrategy('sanitizeParameters')
      .preferredLanguage( language )
}

(3) Afin d'obtenir la langue dans mes fichiers HTML, je l'ai également ajoutée au $rootScope.

run.$inject = ['$window', '$rootScope'];

function run($window, $rootScope ) {
    $rootScope.language = $window.location.pathname.replace(/\//g, '');
}
1
ChezFre