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

Live localization #158

Open
yohanb opened this issue Oct 16, 2012 · 19 comments
Open

Live localization #158

yohanb opened this issue Oct 16, 2012 · 19 comments

Comments

@yohanb
Copy link

yohanb commented Oct 16, 2012

Hi Eric,

Thanks for your great contribution.

Here's my issue:
I need to localize the validation message (i.e.: Field is required) when clicking a "localize" button. My application needs to be able to switch languages (fr-en) in a "live" fashion.

How would you proceed to accomplish this using your plugin?

Thanks!

Yohan

@IFYates
Copy link
Contributor

IFYates commented Oct 23, 2012

Hi Yohan,

I've had a few stabs at trying to get what you're asking for working without changing the library itself.
Eventually, the simplest solution I found was simply to cause a revalidation to take place: http://jsfiddle.net/IanYates83/CVMRA/3/

Ideally, applying localisation would happen live and only update the messages currently shown, but maybe the above will be enough for your needs. I think anything more would require a code change.

Hope that helps

@yohanb
Copy link
Author

yohanb commented Oct 23, 2012

Hi Ian,

Thanks for your response. Your jsfiddle doesn't seem to work as I would have expected. When the Toggle method is called, the validation message is changed but the observable isn't re-validated so the text doesn't change. You have to change the text inputs and re-validate the controls to get the new message.

@IFYates
Copy link
Contributor

IFYates commented Oct 24, 2012

Interesting. I only have IE8 at work (don't get me started), and the button causes the displayed messages to update immediately... I'll take another look at home where I have some sensible browsers.

@Kikketer
Copy link

Kikketer commented May 5, 2014

Sorry about reviving a zombie, but I'm having the same type of issue described above. @IanYates83 I hope you made it home ;)

I'm running ko.validation.localize() to switch the output text when I click the localize button. But my text is never changing either live or on revalidate. I noticed in the validator:

    // create a handler to correctly return an error message
            var errorMsgAccessor = function () {
                if (!config.messagesOnModified || isModified) {
                    return isValid ? null : obsv.error;
                } else {
                    return null;
                }
            };

The second time I run the localize function, the "obsv.error" always returns the first one.

@crissdev
Copy link
Member

@Kikketer You need to revalidate the observable. You might achieve this with observable.valueHasMutated - after applying localization.

@crissdev
Copy link
Member

crissdev commented Feb 6, 2015

This might land in some future version if more people will ask for it. Add your 👍 in the comments if you find this feature needed.
We still have to see how it may fit in the current code base though.

@ghost
Copy link

ghost commented Feb 18, 2015

👍

@RCMax
Copy link

RCMax commented Jun 16, 2015

We need this for the koco project & koco-i18next module. We might try to fork + pull request if we find the time to do it.
👍

@colincbc
Copy link

👍

@one-geek
Copy link

Hello Guys.
First, i recently start using knockoutjs and i really love it. Right now, i'm facing a big problem and its very irritating because so far everything was good. I think i'm facing the same problem as this ticket.
Actually i'm using Globalizejs, a javaScript library for internationalization and localization to translate all JS variable in my application without refreshing the page. The message is assign to an observer and should change, but it doesn't. Please help.

Problem Context:

I think the ko.extenders.required messages are stick to the first assigned text on page load. It doesn't support live validation. Here a example of the code i'm using :

<span data-bind="text: Resource.helloText">Hello default value</span>  // Works
<input type="radio" value="1" data-bind="checked: Person.GenderId, checkedValue: 1" />
<input type="radio" value="2" data-bind="checked: Person.GenderId, checkedValue: 2" />
<span class="text-danger" data-bind="validationMessage: Person.GenderId">Please this field is required</span> // Doesn't switch the text
function ViewModel() {

    self.Person = {
        genderId : ko.observable(false)
    }

    [...]

    /*   // Resource.json English file
    *     'helloText' : 'Hello',
    *     'pageTitle' : 'My Application', 
    *     'genderRequired': 'Please this field is required'

    *    // Resource.json french file
    *     'helloText' : 'Bonjour',
    *     'pageTitle' : 'Mon application ',
    *     'genderRequired': 'Svp ce champ est requis'
    */

    $.getJSON("server/ressource." + Globalize.culture().name.toString() + ".json", function (data) {
            ko.mapping.fromJS(data, {}, self.Resource);
     });

    // Language switcher
    self.SwitchLanguage = function () {
        var activeLang = 'en-CA';

        if (self.LanguageAppId() == 1) {
            self.LanguageAppId(2);
        }
        else {
            self.LanguageAppId(1);
            activeLang = 'fr-CA';
        }

        Globalize.culture(activeLang);

        $.getJSON("server/ressource." + Globalize.culture().name.toString() + ".json", function (data) {
            ko.mapping.fromJS(data, {}, self.Resource);
        });

    }

    [...]

    self.Person.GenderId.extend({ required: { message: self.Resource.genderRequired() } }); 

}

Source : https://github.com/jquery/globalize

@IanYates
Copy link

I'm a lurker on here as I use KO extensively but don't yet use the validation plugin. However, from what I can see in the code given by @Guerson, if the message parameter was updated such that it could take an observable as well as a static string then you'd be gold.

That is, the final line could be

self.Person.GenderId.extend({ required: { message: self.Resource.genderRequired } }); 

Note that the genderRequired observable is not being evaluated.

Knowing very little about the code of this library it doesn't seem like it'd be too big an imposition or change to have the message renderer to use ko.unwrap to grab the message. Actually, for all I know it already does that - give it a try @Guerson

@one-geek
Copy link

Each time the observable is not being evaluated, i have this traceback.

Uncaught TypeError: message.replace is not a function
with a traceback of :
ko.validation.formatMessage @ knockout.validation.debug.js:279validateSync @
knockout.validation.debug.js:877ko.validation.validateObservable @
knockout.validation.debug.js:947(anonymous function) @
knockout.validation.debug.js:831computedFn.evaluateImmediate_CallReadThenEndDependencyDetection @ knockout
3.4.0.debug.js:2142computedFn.evaluateImmediate_CallReadWithDependencyDetection @ knockout
3.4.0.debug.js:2114computedFn.evaluateImmediate @ knockout
3.4.0.debug.js:2078computedFn.evaluatePossiblyAsync @ knockout
3.4.0.debug.js:2044ko_subscribable_fn.notifySubscribers @ knockout-
[...]

@one-geek
Copy link

My guess is that being not evaluated, the code that's calling ko.validation.formatMessage function which is not anymore a string but something not evaluated.

@one-geek
Copy link

Is there a way to remove the validation and re-apply it without refreshing the page?

@crissdev
Copy link
Member

@Guerson You can remove validation of an observable using the validatable extender:

// Set up validation
var obs = ko.observable().extend({required: true, email: true});

// Remove validation
obs.extend({validatable: false});

@one-geek
Copy link

Thank you for your quick answer.

Finally, since all extenders messages are evaluated immediately, I'll change them through a function later and notify all subscribers directly. Only problem is (valueHasMutated/notifySubscribers()) will trigger an form validation.

self.myExtend = self.Person.GenderId.extend({
    required: { message: self.Resource.genderRequired()},
    customExtender: { message: self.Resource.extenderRequired()} 
});

[...]

var obsv = self.myExtend;
obsv.rules()[0].message = self.Resource['genderRequired'](); // required
obsv.rules()[1].message = self.Resource['extenderRequired'](); // customExtender

if (obsv.name == 'observable' && typeof obsv.valueHasMutated === "function") {
    obsv.valueHasMutated();
} else if (observ.name == 'computedObservable' && typeof observ.notifySubscribers === "function") {
    obsv.notifySubscribers();
}

It seems that is the only way for me right now to support my Single-page application.

@slaneyrw
Copy link

We have override the validation template and use a custom binding that uses the validation "message" as a key to look up a localised version of the display message. The localisation is tied to the current culture via a computed and will update all strings on a page without having to re-evaluate the validation conditions if the language is updated. The use the jQuery Globalize library based on Unicode/CLDR, to load and query

@omnoms
Copy link

omnoms commented Mar 14, 2016

I've tried numerous ways of doing what you say you are @slaneyrw . Whatever I try to manipulate the element with, it's overriden by the validation plugin and unsuccessful in doing so.

Even this simple thing; and if I were to make that span's text-data-binding a ko.computed it won't ever be overwritten. It's always the validation message from the plugin.

I can't even get it to update the message with the proper localization bundles. if I have loaded english and swedish, and try to switch with ko.validation.locale("en") and ("se"), having populated the localization with "en" and "se" before attempting to do so and the javascript files for the localization are loaded, it won't update the DOM when doing ko.validation.locale() . If I check the global scope, it has changed for instance ko.validation.rules.required to the appropriate locale, but the DOM is not updated.

@github-clearthought
Copy link

KnockoutValidationFix.zip

For what it's worth, I fixed this. See the above link. Unzip and load page.html in a browser for the demo.

I modified knockout.validation.js and saved as knockout.validation.modified.js. My changes are marked "// Dan". I changed the error message object to a knockout observable. I also added some hooks in knockout.validation.fix.js to handle updating error messages when the bounded language changes. Finally local.js contains a small localization API and the localized strings are stored in localModel.js.

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

No branches or pull requests