Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i use Localize in ready Function ? #57

Open
Naehs opened this issue Sep 17, 2016 · 24 comments
Open

How can i use Localize in ready Function ? #57

Naehs opened this issue Sep 17, 2016 · 24 comments

Comments

@Naehs
Copy link

Naehs commented Sep 17, 2016

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.

@davebaol
Copy link

davebaol commented Oct 9, 2016

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.

@hyyan
Copy link

hyyan commented Oct 10, 2016

You can use it like that:

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

@davebaol
Copy link

davebaol commented Oct 12, 2016

@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. 😞

@Naehs
Copy link
Author

Naehs commented Oct 12, 2016

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.

@davebaol
Copy link

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.

@Naehs
Copy link
Author

Naehs commented Nov 1, 2016

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.

@davebaol
Copy link

davebaol commented Nov 1, 2016

@SheanYu
Try something like this

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

@Naehs
Copy link
Author

Naehs commented Nov 1, 2016

@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 {
      ...
    }
  });

  ...
},

@davebaol
Copy link

davebaol commented Nov 1, 2016

@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)

@Naehs
Copy link
Author

Naehs commented Nov 3, 2016

@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

@davebaol
Copy link

davebaol commented Nov 3, 2016

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

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

@lluisgener
Copy link

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...

@davebaol
Copy link

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

@lluisgener
Copy link

@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?

@davebaol
Copy link

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

@lluisgener
Copy link

lluisgener commented Nov 24, 2016

@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...

@craPkit
Copy link

craPkit commented Feb 21, 2017

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

@Mika83AC
Copy link

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

@lluisgener
Copy link

lluisgener commented Mar 23, 2017

@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.

@Mika83AC
Copy link

Mika83AC commented Mar 23, 2017

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. :)

@lluisgener
Copy link

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.

@Mika83AC
Copy link

Mika83AC commented Mar 24, 2017

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

@craPkit
Copy link

craPkit commented Mar 24, 2017

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

@shaffi
Copy link

shaffi commented Nov 19, 2017

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>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants