14 Replies Latest reply on Sep 23, 2006 6:01 AM by c509

    loading data BEFORE creationComplete

    c509
      Hi,
      i want to do runtime localization. For that i load some XML data and want to bind it to label fields.
      I am holding the localization (its more multilanguage than real localization) in an object.("lang")
      My problem is, that the data has to be known by the applicaion BEFORE the labelfields will be generated. I do not know how to do this. In the labelfields i wrote: {lang.getTerm('somewords')}
      The sequence now seems to be:
      1. Application has been created
      2. labelfields try to "getTerm", but the data which should be in "lang" is not available
      3. language data has been loaded

      Of course this has to to with asynchronous loading, so i have to control the sequence of loading data and getting ready to complete the application.

      I also tried this in the labelfields {lang.somewords}, but then i get an error, that this data is not bindable. Of course i could declare every data which should be used in the labelfields, but that is not the way i want to do it.

      So - how can i control the loading sequence (perhaps using the preloader ? - Example plz?!)

      Thank you in advance
      c509
        • 1. Re: loading data BEFORE creationComplete
          inlineblue Level 1
          If you do your bindings like this, {lang.getTerm('somewords')}, then the best approach is to re-execute all your bindings after the language data is loaded. Make a call to the parent container of all your Labels:

          labelsContainer.executeBindings(true);
          • 2. Re: loading data BEFORE creationComplete
            c509 Level 1
            Ok,perhaps this was a little bit too unclear. Here some code.
            I have this Textfield and try to bind data :
            <mx:Label x="242" y="219" text="{lang.terms.april}" width="155" height="31" fontSize="29" fontFamily="Times New Roman" id="april"/>

            Before that i declare :
            [Bindable]
            public var lang:FG_Lang = new FG_Lang();

            And this is the class:

            package
            {
            import mx.rpc.http.HTTPService;
            import flash.net.*;
            import flash.events.*;
            import mx.utils.*;

            public class FG_Lang
            {
            private var lang:String;
            private var langService:URLLoader;
            public var terms:XML = new XML();
            private function checkresult(event:Event):void
            {
            this.terms = XML(langService.data);
            trace(terms.april); //throws "April"
            }
            public function FG_Lang(lang:String = "de"):void
            {
            this.lang = lang;
            loadLang(lang);
            }
            public function loadLang(lang:String):void
            {
            var request:URLRequest = new URLRequest("data/"+lang+".xml");
            langService= new URLLoader(request);
            langService.addEventListener("complete", checkresult);

            }
            public function getTerm(what:String):String
            {
            return (terms.child(what).toString()); // just another try to get the var ack
            }
            }
            }
            The xml file i load holds:
            "<?xml version="1.0" encoding="utf-8"?>
            <language id="en">
            <april>April</april>
            ....
            </language>"

            The problem is, trying to bind data like
            text="{lang.terms.april}", throws the warning
            "Data binding will not be able to detect assignments to "terms".

            Trying to bind data like:
            text="{lang.getTerm('april')}" throws a runtime error, i think because the data to "getTerm" is not there immediately after "creationComplete"

            k, i hope someone can helpme - thank you

            c509
            • 3. Re: loading data BEFORE creationComplete
              c509 Level 1
              Thanks for replying,

              but i think that would mean to explicitly, "refresh" all label fields ?
              That is, what i do not want, because if i would declare all variables which i wanted to bind, i should have no problem. And explicitly refreshing would e nearly the same "code workload".
              I just want easily use the content of my language object, so i just have to expand my xml file - without declaring and without refreshing explicitly.

              I wrote morecode - perhaps thisis clearer then.
              kind regards
              c509
              • 4. Re: loading data BEFORE creationComplete
                ntsiii Level 3
                Have you tried binding to a function?

                text="{lang.getTerms('april')}"

                Tracy
                • 5. Re: loading data BEFORE creationComplete
                  c509 Level 1
                  Hi Tracy,

                  if you mean something like:
                  text="{lang.getTerm('april')}"
                  - yes i tried it. But as the language data is not been received at the time of the function call, there is no data to grab (i think). This is why i asked for "loading data" before the application event "creationComplete". When writing code in flash i used to "wait" to start the main application as long as a data event like
                  "langService.addEventListener("complete", checkresult);" was fired.
                  But it seems Flex does not have something like that.

                  Perhaps i am totally wrong "HOW" i try so solve to make a runtime localization on the label fields

                  kind rgards,
                  c509
                  • 6. Re: loading data BEFORE creationComplete
                    peterent Level 2
                    How about this....

                    Create 2 SWFs. One is the main.swf which loads the data but has NO ui controls. Once the data has loaded, use SWFLoader to bring in the actual application which can make use of the now-loaded information.
                    • 7. Re: loading data BEFORE creationComplete
                      c509 Level 1
                      Hi Peter,

                      yes i also thought about that kind of solution, but more in "workaround-way".
                      Flex is new to me and i try to learn the "best practice way".
                      I am always thinking, that i do know too less about flex, so perhaps iam walking an odd way to solve things, or i just made a little mistake and thats why my solutions wont work.

                      The 2 swf files solution i slooking like the workaround way, or do you think my code is ok and there is no best practice way ?

                      Perhaps a custom preloader would do it ?
                      Perhaps i could leave the label fields empty, and using the ID of the component., like
                      <mx:Label text="" id="april"/>
                      When finshed reading my xml file (xml tag is the same like the id: "april" and the value is the localizated "April")
                      i could walk thru the data and fill the label fields, identifying them by their id ?!

                      kind regards,
                      c509

                      • 8. Re: loading data BEFORE creationComplete
                        peterent Level 2
                        Flex 2 has the ability to do localization using the ResourceBundle API. The problem with this is that you need to create a separate SWF for each locale. For example, if you have a file of strings for French and one for German and one for English, you need to generate 3 SWFs. The benefit of course is that we've done the bulk of the work for you and it works very closely to the I18n standard.

                        We understand this limitation and are considering options.

                        For the time being, to do dynamic localization I'd go with the two-SWF approach.
                        • 9. Re: loading data BEFORE creationComplete
                          c509 Level 1
                          Hi again,

                          i read about the "static" localization, but as my project will run in nearly every european country(every country another language - in some countrys you have 3(!) different languages) , a runtime localization would be best.

                          I am going to leave thje thread unanswered and hopefully will return with a runtime version, in the middle of next week - perhaps someone is interested in it.

                          Kind regards,

                          c509
                          • 10. Re: loading data BEFORE creationComplete
                            inlineblue Level 1
                            In this case, you don't even need an explicit refresh. You just have to make "terms" property bindable. In your FG_Lang class, just do this:

                            [Bindable]
                            public var terms:XML;

                            And you should be set.
                            • 11. Re: loading data BEFORE creationComplete
                              c509 Level 1
                              Hi,

                              unfortunately this is not working (It was my first thougt, to do it like that)
                              Look at my code, and you will see i am declaring an instance of the class that will read the XML and holds it:
                              [Bindable]
                              public var lang:FG_Lang = new FG_Lang();

                              The problem is, trying to bind data like
                              text="{lang.terms.april}", throws the warning
                              "Data binding will not be able to detect assignments to "terms". <-- what does it mean ?

                              Perhaps the warning is thrown before compiling, because "lang.terms.april" is not known at this time. I am building "terms" and "april" at runtime, so i do not have to declare every single word i want to localize.

                              But perhaps, i have just a little mistake in my code. Plz. take a look at it (some posts above this one)

                              Kind regards,
                              c509 Text public var lang:FG_Lang = new FG_Lang();
                              • 12. Re: loading data BEFORE creationComplete
                                peterent Level 2
                                What you are trying to do is pretty advanced. You'll need to develop some ActionScript classes that extend EventDispatcher so you can make your data bindable. You don't need to do it this way, but it will make it a whole lot easier if you can load your strings into a class that you can write and debug separately.

                                When you use SWFLoader you also have to be aware of Application domains - see ApplicationDomain in the docs. If you choose the wrong type of domain your data won't even be accessible.

                                As for the binding, suppose in the "real" app - the one that will be loaded: you have your strings bound to a class object:

                                <mx:Label text="{MyLocalization.getString('sometitle')}" />

                                where in your resource file you have something like: sometitle="This is a Test"

                                If you define the MyLocalization class with the static method, getString() and MyLocalization has been populated in the main or initial SWF, you should be able to get this work.

                                This is just off the top of my head and I'm sure there are lots of little details to work out, but that's the basic idea.
                                • 13. Re: loading data BEFORE creationComplete
                                  inlineblue Level 1
                                  quote:

                                  Originally posted by: c509
                                  unfortunately this is not working (It was my first thougt, to do it like that)
                                  Look at my code, and you will see i am declaring an instance of the class that will read the XML and holds it:
                                  [Bindable]
                                  public var lang:FG_Lang = new FG_Lang();


                                  Perhaps you didn't read my post correctly. In your case, you don't need to make lang bindable, you must make lang.terms bindable. You do this by declaring the terms property as being bindable in your FG_Lang class. eg:

                                  public class FG_Lang
                                  {
                                  private var lang:String;
                                  private var langService:URLLoader;

                                  [Bindable]
                                  public var terms:XML = new XML();
                                  ....
                                  }

                                  Then at runtime, anytime you assign a new value to the terms property (like in the checkResult method), all the labels will have their values updated.
                                  • 14. Re: loading data BEFORE creationComplete
                                    c509 Level 1
                                    Hi ,

                                    oooh yes ! You were to right. I tried it and it is working !
                                    So, runtime localziation is really an easy thing. (When man knows what hes doing)

                                    Thats exactly what i meant with "perhaps there is a little mistake, because of my little knowledge about flex"

                                    Thank you very much !
                                    c509