javascript - How to handle multiple languages in AngularJS for form validation messages / alerts? -


i'm trying develop app using angularjs should work in multiple, user selected languages. put views in views/en , views/fr, etc, if user viewing in english, template url controllers views/en/somefile.html, , french /views/fr/somefile.html, , on.

the question is, how can handle displaying random form validation messages / alerts displayed javascript, displayed in correct language?

e.g in controllers have $scope.title variable sets <title> in browser. if user selects different language, want <title> updated shown in selected language well.

what's best way of achieving this?

textservice

i have updated answer reflect current solution problem. removing textual data dependence in templates important problem feel , have gone ahead , wrote own little module this. if want use text insertion options (state text , relative text), you'll need use ui-router, configure routes.

here's usage. i'll put module @ end of answer.

  • include text-service.js after angular, before module definition
  • declare dependency: angular.module("app", ["textservice"]
  • bind text data object it. text data object should mimic state hierarchy. e.g.:

     var textdata = {   home: { // 'home' state     // text data home state here     child { // 'home.child' state       // text data child state     }   } } 

    text objects should object literals language names keys:

     var textdata = {   home: {       title: {         en: "home",         fr: "maison"       }     }   } } 

    set language , bind text object textservice:

     app.run(function(textservice) {   var textdata = ...   textservice     .setlanguage("en")     .bindtext(textdata) }); 

    having text data inside run function may not desirable - user if want use factory or number of factories inject this:

     app.factory("textdata", function() {   var textdata = ...   return textdata } app.run(function(textservice, textdata) {   textservice     .setlanguage("en")     .bindtext(textdata) }); 

  • there 4 attribute based directives retrieving text templates. attribute names are:

    1. atext - "absolute text"
    2. stext - "state text"
    3. rtext - "relative text"
    4. text - "text"

    to use template, add, say, atext attribute , set value string locating text data interested in:

     <h1 atext="home.title.en"></h1> 

    all directives replace innerhtml of whatever dom element add text data, make sure has no children dom elements care about.

    the differences in directives locating text strings. suppose had following text data object:

     var textdata = {   title: {     en: "index",     fr: "index"   },   // home state   home: {     title: {en: "home",fr: "maison"},     header: {en: "heading", fr: ""}     child: { // home.child       title: {en: "child",fr: "enfant"},         intro: {           en: "welcome child",           fr: "bienvenue à l'enfant"         }     }     lonelychild: {       // no text data     }   } }; 

    atext refers absolute location of string. atext="title.en" fetches "index" atext="title" throw error (for now).

    stext refers string relative current state. example, if in state 'home', stext="title" fetches "home". if weren't in state @ all, fetch "index". , if navigate 'home.child' state, fetch "child". (note: these provided have set language "en")

    rtext refers relative text location. behaves stext except search state heirarchy looking textual data match well. handy dynamically changing title depending on state:

     <title rtext="title"></title> 

    this replace innerhtml of title dom element nearest 'title' text data. if in state 'home.lonelychild' title still bind "home" (because in parent state's text data).

    text directive works atext, except don't need specify language.

    the directives change dynamically on language change stext, rtext , text. can change language using, e.g., textservice.setlanguage("fr"). $broadcast "languagechange" event text directives indicating should update. if want suppress update, pass second parameter indicating whether update should done: textservice.setlanguage("fr", false)/

    the directives change dynamically on state change stext , rtext.

    you can force update using textservice.update()

    i've gone lengths make plugin fast possible. general rule of thumb, each text directive incur initial processing time of 1ms. think of bulk comes angular initialising directive each piece of text data. following that, dynamic updates quick, if have 100 or text directives on 1 page.


    here's module , link github repo

     /*  * text-service.js  * author: ian haggerty - iahag001@yahoo.co.uk  * last edit: 17/08/2013  */  angular.module("textservice", [])     .factory("textservice", function ($rootscope, $log) {          /* internal implementation */         var textservice;         textservice = {             language: "",             state: "",             textdata: {},              /* text(request) - text request              * @request absolute path text without language appended - e.g. 'home.title'              */             text: function (request) {                 return (new function(                     "return arguments[0].textdata." + request +                         ((textservice.language) ? ("." + textservice.language) : "")                 ))(textservice);             },              /* abstext(request)- absolute text request              * @request absolute path text language appended - e.g. 'home.title.en'              */             abstext: function (request) {                 return (new function(                     "return arguments[0].textdata." + request                 ))(textservice);             },              /* reltext(request, cut) - scoped text request, search state heirarchy              * @request relative path text without language appended - e.g. 'title'              * @state state test textual data - defaults current state, used recursively              */             reltext: function (request, state) {                 if(state === undefined) {                     // initial call function                     state = textservice.state                 }                 try { return textservice.text((state?state+".":"") + request)}                 catch(e) {                     if(!state) return "" // terminate avoid infinite recursion                     return textservice.reltext(request, state.split(".")).slice(0,-1).join(".");                 }             },              /* statetext - request string in current state(e.g. statetext('title')              * @request - relative path string in current state              */             statetext: function (request) {                 return (textservice.state) ?                     textservice.text(textservice.state + "." + request) : "";             }         }          // register handler state changes         $rootscope.$on("$statechangesuccess", function (event, tostate) {             textservice.state = tostate.name;         });          /* public api */         var textserviceapi = {             /* bindtext - bind entire textual data new object              * @textdata - text data object bound              */             bindtext: function (textdata) {                 textservice.textdata = textdata;                 $rootscope.$broadcast("textdatachange")                 return textserviceapi;             },             /* settext() - function set textual data , update text directives              * @request request string, e.g. 'home.title', 'home.title.en'              * @textdata textual data. literal string or object textual data              * @doupdate boolean indicating whether update text directives. defaults false.              * example usage 1: settext('home.title.en', "title") - set text string without update              * example usage 2: settext('home.title', {en:"title", fr:"maison"}, true)              * - set text object update page              */             settext: function(request, textdata, doupdate) {                 (new function(                     "arguments[0].textdata." + request + "=arguments[1]"                 ))(textservice, textdata)                 if(!doupdate) $rootscope.$broadcast("textdatachange")                 return textserviceapi             },             /* gettext() - function returning textual data              * @request absolute reference text              * example usage: gettext('home.title.en'), gettext('home.title') // returns text object              */             gettext: function(request) {                 if(!request)                     return textservice.textdata                 else {                     return (new function(                         "return arguments[0].textdata." + request                     ))(textservice)                 }             },             /* setlanguage() - set current language              * @langauge  - new language. e.g. "fr", "en"              * @doupdate - boolean indicating whether update text directives, defaults true              * example usage: setlanguage("fr") // change french , update page              */             setlanguage: function (language, doupdate) {                 if(doupdate === undefined) doupdate = true;                 textservice.language = language                 $rootscope.$broadcast("languagechange")                 return textserviceapi;             },             getlanguage: function () {                 return textservice.language;             },             /* update() - requests text directives update              */             update: function() {                 $rootscope.$broadcast("textdatachange")                 return textserviceapi             },             /* used text directives */             text: textservice.text,             abstext: textservice.abstext,             reltext: textservice.reltext,             statetext: textservice.statetext         }         return textserviceapi     })     /* text directive */     .directive("text", function (textservice) {         return {             restrict: "a",             link: function (scope, element, attrs) {                 function update() {                     element.html(textservice.text(attrs.text))                 }                  scope.$on("languagechange", update)                 scope.$on("textdatachange", update)                  update()             }         }     })     /* absolute text directive */     .directive("atext", function (textservice) {         return {             restrict: "a",             link: function (scope, element, attrs) {                 function update() {                     element.html(textservice.abstext(attrs.atext))                 }                  scope.$on("textdatachange", update)                  update()             }         }     })     /* state text directive */     .directive("stext", function (textservice) {         return {             restrict: "a",             link: function (scope, element, attrs) {                 function update() {                     element.html(textservice.statetext(attrs.stext))                 }                  scope.$on("languagechange", update)                 scope.$on("textdatachange", update)                 scope.$on("$statechangesuccess", update)                  update()             }         }     })     /* relative text directive */     .directive("rtext", function (textservice, $log) {         return {             restrict: "a",             link: function (scope, element, attrs) {                 function update(event, request) {                     element.html(textservice.reltext(attrs.rtext))                 }                  scope.$on("languagechange", update)                 scope.$on("textdatachange", update)                 scope.$on("$statechangesuccess", update)                  update()             }         }     })  

  • Comments

    Popular posts from this blog

    css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

    gcc - Calling fftR4() in c from assembly -

    .htaccess - Matching full URL in RewriteCond -