Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

21avr/093

Flex Localization – Chargement de Resource Modules à la volée

Pour charger un Resource Module à l'exécution, vous allez utiliser la méthode loadResourceModule() du ResourceManager. Une fois que le Resource Module a fini son chargement, vous pouvez fixer la valeur de la propriété localeChain à une nouvelle valeur correspondant à la locale que vous venez de charger.

La méthode loadResourceModule() de ResourceManager est une méthode asynchrone (pouvant être comparée à la méthode loadStyleDeclarations() du StyleManager qui charge des themes Flex).

La méthode loadResourceModule() prend plusieurs paramètres. Le premier paramètre est l'URL du fichier SWF  du Module. C'est le seul paramètre obligatoire. Le second paramètre est "update". Vous pouvez le mettre à true ou false, suivant si vous voulez que l'application soit mise à jour tout de suite après le chargement du RM. Les deux paramètres suivants sont applicationDomain et securityDomain. Ces paramètres spécifient les domaines dans lesquels les Resource Modules sont chargés. Ces derniers ne sont nécessaires que si vous essayez de charger de modules venant d'autres domaines que celui où est hébergé l'application.

La méthode loadResourceModule() retourne une instance de la classe IEventDispatcher. Vous pouvez utiliser cet objet pour dispatcher des évènements de type ResourceEvent, qui vont indiquer le succès ou l'échec du chargement du module. Vous aurez accès aux évènements ResourceEvent.PROGRESS, ResourceEvent.COMPLETE et ResourceEvent.ERROR pendant le chargement.

Vous ne pouvez pas appelez la méthode loadResourceModule() et immédiatement essayer d'y accéder car le module SWF doit être téléchargé (asychrone) . Vous devez donc ajouter un event handler sur ResourceEvent.COMPLETE et modifier localeChain à ce moment-là.

L'exemple suivant charge un Resource Module quand l'utilisateur choisit une langue depuis une ComboBox. Il construit le nom du module (soit  en_US_ResourceModule.swf, soit es_ES_ResourceModule.swf) et passe ce nom à la méthode loadResourceModule():

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp()">
    <mx:Script><![CDATA[
    	import mx.resources.ResourceManager;
        import mx.resources.ResourceBundle;
        import mx.controls.Alert;
        import mx.events.ResourceEvent;

        [Bindable]
        private var locales:Array = [ "fr_FR","en_US" ];

        private function initApp():void {
            // Set the index to -1 so that the prompt appears when the application first loads.
            localeComboBox.selectedIndex = -1;
        }

        private function registrationComplete():void {
            Alert.show(resourceManager.getString('RegistrationForm', 'thanks'));
        }  

        private function comboChangeHandler():void {
            var newLocale:String = String(localeComboBox.selectedItem);

            // Ensure that you are not loading the same resource module more than once.
            if (resourceManager.getLocales().indexOf(newLocale) != -1) {
                completeHandler(null);
            } else {
                // Build the file name of the resource module.
                var resourceModuleURL:String = newLocale + "_ResourceModule.swf";

                var eventDispatcher:IEventDispatcher = resourceManager.loadResourceModule(resourceModuleURL);
                eventDispatcher.addEventListener(ResourceEvent.COMPLETE, completeHandler);
            }
        }

        private function completeHandler(event:Event):void {
            resourceManager.localeChain = [ localeComboBox.selectedItem ];

            // This style is not bound to the resource bundle, so it must be reset when
            // the new locale is selected.
            b1.setStyle("downSkin", resourceManager.getClass("RegistrationForm", "flag"));
        }
    ]]></mx:Script>

    <mx:Metadata>
        [ResourceBundle("RegistrationForm")]
    </mx:Metadata> 

    <mx:Image source="{resourceManager.getClass('RegistrationForm', 'flag')}"/>

    <mx:ComboBox id="localeComboBox"
        prompt="Select One..."
        dataProvider="{locales}"
        change="comboChangeHandler()"
    />

    <mx:Form>
        <mx:FormItem label="{resourceManager.getString('RegistrationForm','personname')}">
            <mx:TextInput/>
        </mx:FormItem>
        <mx:FormItem label="{resourceManager.getString('RegistrationForm','street_address')}">
            <mx:TextInput/>
        </mx:FormItem>
        <mx:FormItem label="{resourceManager.getString('RegistrationForm','city')}">
            <mx:TextInput/>
        </mx:FormItem>
        <mx:FormItem label="{resourceManager.getString('RegistrationForm','state')}">
            <mx:TextInput/>
        </mx:FormItem>
        <mx:FormItem label="{resourceManager.getString('RegistrationForm','zip')}">
            <mx:TextInput/>
        </mx:FormItem>
    </mx:Form>
    <mx:Button id="b1" label="{resourceManager.getString('RegistrationForm','submit_button')}" click="registrationComplete()"/>
</mx:Application>

Flex Source Code Download: Télécharger le code source complet de l'application

This movie requires Flash Player 11

Pour compiler une application qui n'utilise que des resources Modules, ne spécifiez aucune locale à la compilation. Pour cela, laissez l'option -locale à une chaine vide. Par exemple, en ligne de commande, vous devrez compiler MyApp.mxml avec la ligne de commande suivante:

mxmlc -locale= MyApp.mxml

Dans Flex Builder, indiquer simplement ce qui suit dans le champ Additional Compiler Arguments du panneau de propriétés du projet:

-locale=

Si vous compilez une application qui utilise à la fois des ressources de langues compilées et des modules, vous devez spécifier les locales compilées dans l'option locale.

Vous devrez ensuite essayer de ne pas charger le même Resource Module plusieurs fois dans une application. Pour cela, vous pouvez utiliser la méthode getLocales() du ResourceManager. Cette méthode retourne un Array de locale. Vous pouvez comparer cette liste avec la locale du RM que vous allez charger.

Vous pouvez aussi  savoir quel RB existe pour une locale en particulier avec la méthode getBundleNamesForLocale().

Vous pouvez récucpérer une référence  vers un Resource Bundle en particulier en appelant la méthode getResourceBundle(). Une fois que vous avez cette référence vers le Resource Bundle, vous pouvez utiliser une boucle "for in" pour itérer sur le contenu du Resource Bundle.

Articles similaires

Commentaires (3) Trackbacks (0)
  1. Bonjour,

    juste une question svp : sans utiliser le getBundleNamesForLocale() pour tester le chargement préalable ou non d'un RB et en mode debug, si je tente de charger un RB pour une locale plusieurs fois de suite, il semble que celui soit chargé uniquement une fois. En effet, je ne vois apparaitre le :

    [SWF] E:\workspaces\flex\sim_test\locales\bin-debug\resources\en_US_resourceBundle.swf - 66 812 octets après la décompression

    qu'une seule fois.

    Se peut il donc que le système "voit" que le RB a déjà été chargé et refuses de le charger une nouvelle fois ? Si tel est le cas, à quoi peut donc servir le getBundleNamesForLocale() si le système fait implicitement ce travail de vérification d'existence ou non du RB avant son chargement ?

    Merci d'avance de vos éclaircissements et bonne continuation pour ce blog, véritable mine d'informations pour les flexeurs frenchies :)

  2. Salut,
    Et bien elle peut te servir à faire la vérification avant, pour éviter de le charger 2 fois justement, non?

    Fabien

  3. Salut et merci de ta réponse Fabien

    En fait je pense , sans pour autant en être sur, que quoi qu'il arrive, un RB ne pourra être lancé en chargement qu'une seule fois. En effet, comme j'essayais de l'expliquer avant, sans faire de test de vérification via getBundleNamesForLocale() du chargement préalable d'un RB, si je relance le chargement d'un RB (déjà chargé) celui ci ne s'effectue pas car Flex doit savoir que ce RB a déjà été chargé auparavant.

    D'où ma question : si le mécanisme de Flex détecte et interdit le chargement de 2 fois le même RB, à quoi peut donc servir la fonction getBundleNamesForLocale()...?

    Je précise toutefois que l'on rentre dans ResourceEvent.COMPLETE, simplement le rechargement ne se fait pas, on rentre dans le handle de l'événement immédiatement.

    Du moins tout ça...ca ne reste que ma vision des choses ! Je constate simplement qu'en mode debug, quoi que je fasse, le chargement du swf ne s'effectue au maximum qu'une fois


Leave a comment

(required)

Aucun trackbacks pour l'instant