patryk
patryk

Reputation: 651

Durandal multilingual app, page/module title as an observable, changing document.title dynamically

I am working on localizing my durandal application. I have already chosen an approach - I am sharing a module across all my pages containing all the strings that any view may have.

In my shell I am defining

router.map([
    { route: ['', 'search'], title: i18n.search, moduleId: 'viewmodels/search/index', nav: true },
    { route: "employees", title: i18n.employeesList, moduleId: "viewmodels/employees/index", nav: false },
    { route: "details/:id", title: i18n.details, moduleId: "viewmodels/details/index", nav: false }
    // ...
]);

where the i18n properties are ko.observables containing strings like

i18n = {
    search: ko.observable("search"),
    employeesList: ko.observable("employeesList"),
    details: ko.observable("Details")
}

This works fine printing my navigation bar with

<ul class = "nav navbar-nav" data-bind = "foreach: router.navigationModel">
    <li data-bind = "css: { active: isActive }">
        <a data-bind = "attr: { href: hash }, text: title"></a>
    </li>
</ul>

however when it comes to having the document title changed, it does not work.

Here I found something about durandal setting the document.title, unfortunately the answer suggests that to change the title durandal creates some other properties (that seem to be based on my title module object declaration property) and probably does not assume that the title might be something other than a string.

Is there a way to override some method that durandal uses to change the document.title or any other way to make it change document.title when navigating?

Upvotes: 1

Views: 901

Answers (2)

Sander Teunissen
Sander Teunissen

Reputation: 61

This might come a little late, but I'd like to add my solution too :-) I am using observables which change the text of my variables on demand. When setting the routes and their options like this:

var routes = [{ route: '', title: 'Welcome', moduleId: 'viewmodels/welcome', nav: true, title: 
    ko.computed(function () { return activeTranslation.welcome() }) 
}];

my activeTranslation looks something like this:

var activeTranslation = {
    welcome: ko.observable()
}

Now when changing the language I just have to loop through my language object containing the same variables and their respective translation and apply them to the observable.

var dutch = { welcome: "Welkom" };

function loadLanguage (lang) {
    for (var key in languages[lang]) {
        activeTranslation[key](languages[lang][key]);
    }
}

Upvotes: 2

RainerAtSpirit
RainerAtSpirit

Reputation: 3723

You can follow the steps outlined in Durandal.js 2.0 Set document title within activate method.

You'd need to overwrite router.updateDocumentTitle in main.js|shell.js so that it takes into account that config.title is an observable.

Something along the following should get you started.

router.updateDocumentTitle = function(instance, instruction) {
    if (instruction.config.title) {
        if (app.title) {
            document.title = ko.unwrap(instruction.config.title) + " | " + app.title;
        } else {
            document.title = ko.unwrap(instruction.config.title);
        }
    } else if (app.title) {
        document.title = app.title;
    }
};

Update: Based on comment.

In addition to the modification above if the title should change immediately then there's some more work required.

Reason is that router doesn't know about language switching. Pub/sub is most probably the right way for the implementation. Consider setting up an event e.g using app.on that changes the document.title. router.activeInstruction() will provide access to the config object. Trigger the event whenever somebody is switching in whatever view model.

Upvotes: 4

Related Questions