app-localize-behavior icon indicating copy to clipboard operation
app-localize-behavior copied to clipboard

How can i use Localize in ready Function ?

Open Naehs opened this issue 8 years ago • 24 comments

Hi :)

Localization behavior is working fine for me, but i don't know if i can use it in a ready function and how. For exemple, for a login form, i want to show a toast with different informations in two language.

If login are good : {{localize('login_succeeded', 'pseudo', event.detail.response.pseudo)}} If login are wrong : {{localize('login_failed')}} If error : {{localize('login_error')}}

My code :

<div class="container flex-center-justified flex-center-align">
      <div class="inner-container">
        <img src="../images/myApp.png" alt="myApp">
        <h2>myApp</h2>
        <form is="iron-form" method="post" action="../API/v1/index.php/login" id="loginForm">
          <paper-input type="text" name="pseudo" label="{{localize('login_pseudo')}}" no-label-float required></paper-input>
          <paper-input type="password" name="password" label="{{localize('login_password')}}" no-label-float required></paper-input>
          <paper-button noink on-tap="_submit">{{localize('login_submit')}}</paper-button>
          <div class="output"></div>
        </form>
      </div>
    </div>
    <paper-toast id="toast"></paper-toast>
  </template>

  <script>
    Polymer({
      is: 'my-login',

      behaviors: [
        Polymer.AppLocalizeBehavior
      ],

      properties: {
        language: {
          value: 'fr',
          type: String
        }
      },

      attached: function() {
        this.loadResources(this.resolveUrl('locales.json'));
      },

      ready: function() {
        var loginForm = this.$.loginForm;
        var request = loginForm.request;
        var toast = this.$.toast;

        loginForm.addEventListener('iron-form-response', function(event) {
          console.log("Form Error: ",event.detail.response.error);
          if (event.detail.response.error) {
            message = localize('login_failed');
            toast.show({text: message, duration: 5000});
          } else {
            message = localize('login_succeeded', 'pseudo', event.detail.response.pseudo);
            toast.show({text: message, duration: 5000});
          }
        });

        loginForm.addEventListener('iron-form-error', function(event) {
          message = localize('login_error');
          toast.show({text: message, duration: 5000});
        });
      },

      _submit(event) {
        Polymer.dom(event).localTarget.parentElement.submit();
      }
    });
  </script>

locales.json

{
  "en": {
    "login_succeeded": "Greetings {pseudo} !",
    "login_failed": "Incorrect IDs.",
    "login_error": "Oops, an error occurred !",
    "login_pseudo": "Nickname",
    "login_password": "Password",
    "login_submit": "Connection"
  },
  "fr": {
    "login_succeeded": "Salutations {pseudo} !",
    "login_failed": "Identifiants incorrects.",
    "login_error": "Oups, une erreur est survenue !",
    "login_pseudo": "Surnom",
    "login_password": "Mot de passe",
    "login_submit": "Connexion"
  }
}

Thanks. Greetings Loïc.

Naehs avatar Sep 17 '16 10:09 Naehs

I think it should be this.localize('login_failed'), not just localize('login_failed'). However I got it working from inside regular functions only, not from inside lifecycle functions like ready or even attached. Not sure why, though. Maybe this has something to do with computed properties.

davebaol avatar Oct 09 '16 20:10 davebaol

You can use it like that:


this.async(function(){
    this.localize('translation')
},100);

hyyan avatar Oct 10 '16 06:10 hyyan

@hyyan Thanks, this looks like an acceptable solution most of the times. However it's still not clear why computed functions are not available in lifecycle functions. It seems that Polymer documentation is lacking on this topic. :disappointed:

davebaol avatar Oct 12 '16 07:10 davebaol

Thanks guys !

I will try it later. In the case where i want to call a function inside the ready function or a normal function, how it's work ?

For example : See the showToast() function

<script>
 Polymer({
   is: 'my-login',

   ready: function() {
     this.async(function() {
       this.showToast("This is a message...");
     },100);
   },

   otherFunction: function() {
     this.showToast("This is a message...");
   },

   showToast: function(message) {
     toast.show({text: message, duration: 5000});
   }
 });
</script>

Thanks, Loïc.

Naehs avatar Oct 12 '16 07:10 Naehs

Just replace the text message with this.localize('myKey'); Also, about the function you're passing to async, you should either bind it to this or make it an arrow function.

davebaol avatar Oct 12 '16 09:10 davebaol

Hi guys !

I tried this after your recommendation :

toastMessage.show({horizontalAlign: 'right', verticalAlign: 'top', duration: 5000, text: this.async(function() { this.localize('login_failed'); },100)});

And I still have :

Uncaught ReferenceError: this.localize is not defined(…)

Loïc.

Naehs avatar Nov 01 '16 18:11 Naehs

@SheanYu Try something like this

this.async((function() { 
  toastMessage.show({
    horizontalAlign: 'right',
    verticalAlign: 'top',
    duration: 5000,
    text: this.localize('login_failed')
  });
}).bind(this), 100);

davebaol avatar Nov 01 '16 19:11 davebaol

@davebaol Same error...

Note that i'm in the ready function :

ready: function() {
  ...

  loginForm.addEventListener('iron-form-response', function(event) {
    if (event.detail.response.error) {
      this.async((function() { 
        toastMessage.show({
          horizontalAlign: 'right',
          verticalAlign: 'top',
          duration: 5000,
          text: this.localize('login_failed')
        });
      }).bind(this), 100);
    } else {
      ...
    }
  });

  ...
},

Naehs avatar Nov 01 '16 19:11 Naehs

@SheanYu Actually, that code is executed out of the ready function since it's an event handler. You just have to bind the event handler to this like that (function(event) {...}).bind(this)

davebaol avatar Nov 01 '16 22:11 davebaol

@davebaol

With this :

ready: function() {
  ...

  loginForm.addEventListener('iron-form-response', function(event) {
    if (event.detail.response.error) {
      this.async((function() { 
        toastMessage.show({
          horizontalAlign: 'right',
          verticalAlign: 'top',
          duration: 5000,
          text: this.localize('login_failed')
        });
      }).bind(this), 100);
    } else {
      ...
    }
  }).bind(this);

  ...
},

I got this error :

Uncaught TypeError: Cannot read property 'bind' of undefined(…)

ready  @ my-login.html:165
_invokeBehavior @ polymer-micro.html:455
_doBehavior @ polymer-micro.html:445
_readySelf @ polymer-mini.html:88
_ready @ polymer-mini.html:75
_tryReady @ polymer-mini.html:60
_initFeatures @ polymer.html:4053
createdCallback @ polymer-micro.html:202
window.Polymer @ polymer-micro.html:65
(anonymous function) @ my-login.html:124

Naehs avatar Nov 03 '16 20:11 Naehs

@SheanYu Well, you're binding this to nothing. This should make it work

  loginForm.addEventListener('iron-form-response', (function(event) {
    ...
  }).bind(this));

davebaol avatar Nov 03 '16 20:11 davebaol

I'm having problems too with localize in the ready event. It says localize is not a function.

The (ugly) async approach works most of the times, but sometimes 100ms is not enough and it fails. I know I can increase the timeout, but I think it would be better to have a solution to make it always work.

I understand that resources may not yet be loaded, but I expect it to be another kind of error...

lluisgener avatar Nov 24 '16 15:11 lluisgener

I understand that resources may not yet be loaded, but I expect it to be another kind of error...

I don't think it's a matter of resources not loaded yet

davebaol avatar Nov 24 '16 15:11 davebaol

@davebaol Me neither, I think it has something to do with the computed properties and the way Polymer handles them. But, why not make localize a regular function?

lluisgener avatar Nov 24 '16 16:11 lluisgener

@lluisgener Because being localize a computed property when language or resources change all [[localize(...)]] are dynamically re-calculated.

davebaol avatar Nov 24 '16 16:11 davebaol

@davebaol I see. But I guess only bound localizations are re-calculated, not the ones invoked programatically. So maybe a good solution would be to keep the computed property as is, and also have a regular function which should be the recommended in a no-bound usage.

Or make the Polymer team invoke the ready event when computed properties have been initialized, if it's possible...

lluisgener avatar Nov 24 '16 16:11 lluisgener

It seems you can work around this issue using computed properties, like this:

Polymer({
  properties: {
    errorMessage: {
      type: String,
      computed: '_initErrorMessage(localize)'
    },
  },
  _initErrorMessage: function(localize) {
    return localize('myMsg');
  }
});

craPkit avatar Feb 21 '17 11:02 craPkit

So is there even any way of calling localize from within a polymer element, indifferent of in the ready() function or any other element function?

As it is usual to process UI texts in functions, it is necessary to grab translations in the code and then pass it to the UI.

Regards, Michael

Mika83AC avatar Mar 23 '17 14:03 Mika83AC

@Mika83AC look at @craPkit post. It worked flawlessly for me. But you need to tweak a little your code to correctly use computed properties.

Regards.

lluisgener avatar Mar 23 '17 14:03 lluisgener

Hm... sure, this is possible but creates an immense overhead (code size, complexity ...). This is just not possible for larger applications and can't be the solution the Polymer team wants to see.

So I really hope they have another solution for us. :)

Mika83AC avatar Mar 23 '17 15:03 Mika83AC

I think that it's the way to go, because localize is a computed method to be able to change language during execution, and I think the better way to do it is with a calculated method, as it is.

lluisgener avatar Mar 23 '17 15:03 lluisgener

** Removed because of completely bullshit, sorry :D **

Mika83AC avatar Mar 24 '17 09:03 Mika83AC

Doesn't this.localize('translationKey') work outside of ready() anyway?

craPkit avatar Mar 24 '17 12:03 craPkit

I manage to resolve this way

<link rel="import" href="../bower_components/app-localize-behavior/app-localize-behavior.html">

<dom-module id="x-custom">

  <template>
    <span> [[_greetings(name, localize)]]</span>
  </template>

  <script>
    Polymer({

      is: 'x-custom',
      behaviors: [
          Polymer.AppLocalizeBehavior
      ],
      properties: {
        name: String,
        language: { type: String,  value: 'zh-CN' }
      },
      attached: function() {
        this.loadResources(this.resolveUrl('locales.json'));
      },
      _greetings: function(name, localize) {
        return  localize('hello')+ ' ' + name;
      }

    });
  </script>

</dom-module>

shaffi avatar Nov 19 '17 19:11 shaffi