PDA

View Full Version : Ext.LocaleManager



mitchellsimoens
4 Aug 2011, 3:40 PM
Want to dynamically load locale files? Ext.LocaleManager can load a JS script tag on the fly.

Want to refer to locale text easily in your application? Ext.LocaleManager has a simple get method that you can use to access locale text even if the text is nested.

https://github.com/mitchellsimoens/Ext.LocaleManager

Easy to setup and use:


Ext.LocaleManager.setConfig({
language : 'en', //default is 'en'
ns : 'locale', //default is 'locale'
path : '/locale' //default is 'locale'
});

Ext.onReady(function() {
var callback = function(manager) {
console.log(manager.get('helpText'));
console.log(manager.get('button.action'));
};

Ext.LocaleManager.loadLocale(callback);
});

Sample locale looks like:


{
helpText : 'Click me for help',
buttons : {
action : 'Action'
}
}

On my wishlist:


Get into the Ext JS 4.x framework
Support Ajax loading, not just script tag loading (Added 8/5/11)
More advanced locale settings like date differences


Updated (8/5/11):


Ajax support! (need feedback)
Default text parameter on get method
New Ajax example
Update Simple example to show default text usage
Updated MVC app example to have a language ComboBox

Dumbledore
5 Aug 2011, 3:04 AM
Nice! I will implement this in my application...

Dumbledore
5 Aug 2011, 4:11 AM
just an idea... it will better to have a default value like this...



Ext.LocaleManager.get('fields.title', 'My Title');

mitchellsimoens
5 Aug 2011, 4:46 AM
I like that idea. Tonight I will be working on this some more to include Ajax support and will fold this in. This suggestion to add will not hard at all :)

Keep up the suggestions! So far this is very simplistic but very needed IMO.

mitchellsimoens
5 Aug 2011, 5:59 PM
Here are some changes I just made:


Ajax support! (need feedback)
Default text parameter on get method
New Ajax example
Update Simple example to show default text usage
Updated MVC app example to have a language ComboBox


As always, let me know so I can keep improving!

Henrik Rutzou
8 Aug 2011, 8:56 AM
Hi,

here is another way that I use in v3.3:

Translation of general text used in controllers is done in the browser by adding a javascript file with the appropriate language:




1. A simple javascript translate file are included in the main page:

function i18n(translate) {
switch (translate) {

case 'Search' : return 'Søg';
case 'Search:' : return 'Søg:';
case 'Create' : return 'Opret';
.....

// Return Default Value
default : return translate;
}
}


2. Example of code in the Controller:

{xtype:'label'
,text: i18n('Search:')
,cls: 'ytb-text'
}


For i18n translation of text in forms, grids, combo's and even data, dateformats and punctuation is done on the server because I use templates and metadata and all view's are generated "on the fly" by the server based on what language the user selected on the session, what design the user has been set up to and the rules for the user or the user group he belongs to:

http://216.109.205.54/pextcgi/pxdctemp.pgm?template=date

(http://216.109.205.54/pextcgi/pxdctemp.pgm?template=date)The server can be set in collection mode and will collect all text used by an application in a table where it can be "raw" translated using google translate api and then afterwards manually adjusted.

mberrie
25 Aug 2011, 12:24 AM
Hi mitchell,

I have been thinking about the asynchronous character of the load operation in LocaleManager.

I can see that you trigger the load in Application.launch and then delay the viewport creation until the locale data has been loaded.

IMHO the LocaleManager should trigger the file loading earlier in the application load process and then delay execution of Application#launch until the data is loaded.
Of course this is an optimization that might not be required at this stage in development.

Another issue I see is that you cannot use LocaleManager as part of the class definition, e.g.
[CODE]
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',

title: Ext.LocaleManager.get('mypanel.title');
});

but have to defer calls to LM#get() to within the constructor/initComponent or later.


I wonder if it would make sense to load the language data in a blocking script tag that would guarantee that the data is loaded and LocaleManager is ready to serve requests long before Ext.onReady().

Changing the language at runtime is nice. Is it safe to use viewport.destroy() and re-launch the application?

What do you think?

mitchellsimoens
25 Aug 2011, 4:47 AM
They way I did it was the easiest instead of hacking Ext.app.Application.

About not being able to define title, why not put the all locale text into initComponent or constructor?

You don't need to destroy your Viewport... just remove and add items.

mberrie
25 Aug 2011, 6:33 AM
About not being able to define title, why not put the all locale text into initComponent or constructor?


Sure :) that's what I meant by writing this:


Another issue I see is that you cannot use LocaleManager as part of the class definition [...] but have to defer calls to LM#get() to within the constructor/initComponent or later.

It would be more robust if LocaleManager didn't have this restriction.

IMHO localization is a very low level service in terms of application infrastructure, and should be available also for configs that are passed to Ext.define.

However, a downside of this would be that switching language by re-creating the UI components (destroy and relaunch) would not affect those localized values because the class definition itself is not re-executed.


I still worry that switching the language this way asks for troubles with tangled objects etc. Do you know what the lifecycle of controllers is in this scenario.
Looking at your MVC example app, the controllers are correctly bound to the new viewport. That's neat!
Will the call to Application#launch cause new instances of controllers to be created, and if so, what happens to the old ones.

Just trying to give feedback here!

mitchellsimoens
25 Aug 2011, 6:44 AM
You say localization is low level except when you have to support it, it's actually very important. If you define things like title in initComponent and the LocaleManager has been loaded, you don't have any problems then.

The launch method won't be called again as it's only called once like onReady would be so no worries there. That being said, getController will first look to see if the controller exists, if not it will create it. Same goes for getStore and the others.

mberrie
25 Aug 2011, 7:14 AM
You say localization is low level except when you have to support it, it's actually very important.
Of course it is very important! With 'low-level' I meant it should be a service/component at the very core of the application framework.

That's why I like that you only have dependencies on Ext.core.



The launch method won't be called again as it's only called once like onReady would be so no worries there. That being said, getController will first look to see if the controller exists, if not it will create it. Same goes for getStore and the others.

I was referring to the language-change mechanism. This will call app.launch() to recreate the view.


However, after digging a bit into the source of the MVC framework I couldn't find any obvious reason why it should cause problems.

So I probably should have done that before - I hesitated to do that thinking the MVC code would be more comlex, but it actually seems to be a very slick and concise architecture.

mitchellsimoens
25 Aug 2011, 7:16 AM
So I probably should have done that before - I hesitated to do that thinking the MVC code would be more comlex, but it actually seems to be a very slick and concise architecture.

Yeah, looking at it the first time when it was created, was kind of surprised how simple it actually is :)

jmaia
1 Sep 2011, 7:31 AM
Hi,

I'm using Ext.LocaleManager to localize my app (great stuff, by the way) but I'm getting an error when the locale file does not exist. The error happens in the following line:

head.appendChild(script);
on the method loadScriptTag in Ext.LocaleManager.js

Is it possible to avoid this error from happening, so that when the locale file is not found it just uses the default strings provided on the second parameter of the get method ? I tried using a try catch around it but it didn't really work, because the error is not really a javascript error but a 404 because the resource I'm trying to use does not really exist on the server. So it would be neat to actually check if the locale file exists before including it on the html file as a script tag. And if not don't load the locale file and just go on merrily.

The reason I'm asking this is because my application will try and find the current language preferences of the user's browser and should try to load a locale file base on that preference. But if there is no locale file for that language preference it should just go on and user whatever is supplied on the default parameters.

Regards,

Joao Maia

mitchellsimoens
1 Sep 2011, 7:33 AM
Nice idea! Will look into it!

It happens when the url of the locale file returns 404?

jmaia
1 Sep 2011, 7:36 AM
Hi,

Thanks for the reply.

Yep, I'm using Firebug and what happens is I get a 404 on the console when the url points to a non-existant locale file.

Regards,

Joao Maia

mitchellsimoens
1 Sep 2011, 7:38 AM
Hi,

Thanks for the reply.

Yep, I'm using Firebug and what happens is I get a 404 on the console when the url points to a non-existant locale file.

Regards,

Joao Maia


Ok thanks! Will look into adding this error support!

galdaka
2 Sep 2011, 3:11 AM
Hi mitchell,

I have been thinking about the asynchronous character of the load operation in LocaleManager.

I can see that you trigger the load in Application.launch and then delay the viewport creation until the locale data has been loaded.

IMHO the LocaleManager should trigger the file loading earlier in the application load process and then delay execution of Application#launch until the data is loaded.
Of course this is an optimization that might not be required at this stage in development.

Another issue I see is that you cannot use LocaleManager as part of the class definition, e.g.
[CODE]
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',

title: Ext.LocaleManager.get('mypanel.title');
});

but have to defer calls to LM#get() to within the constructor/initComponent or later.


I wonder if it would make sense to load the language data in a blocking script tag that would guarantee that the data is loaded and LocaleManager is ready to serve requests long before Ext.onReady().

Changing the language at runtime is nice. Is it safe to use viewport.destroy() and re-launch the application?

What do you think?

Same "problem". I´m agree with mberrie (http://www.sencha.com/forum/member.php?239934-mberrie).

Defer calls to LM#get() to within the constructor/initComponent or later is not clean.

Is posible change this?

Thanks in advance and excellent work!!!

mitchellsimoens
2 Sep 2011, 4:48 AM
The problem doing it there is the LocaleManager would have to stop everything and then continue where it left off. Class files could not be loaded and in a build that is impossible without having a sync call (which including script files isn't really).

galdaka
4 Sep 2011, 10:51 PM
The problem doing it there is the LocaleManager would have to stop everything and then continue where it left off. Class files could not be loaded and in a build that is impossible without having a sync call (which including script files isn't really).

Would be posible combine your code with this: http://www.sencha.com/forum/showthread.php?145847-Ext.LocaleLoader-to-dynamically-load-and-apply-your-locale-files-(ExtJS-MVC)

I (http://www.sencha.com/forum/showthread.php?145847-Ext.LocaleLoader-to-dynamically-load-and-apply-your-locale-files-(ExtJS-MVC))ntegrate you LocaleLoader with Ext.Loader...

Otherwise:

1) How can I combine your code in any "initComponent"? Is posible but more dirty.
2) How can I change language dinamically?

Thanks in advance,

mitchellsimoens
5 Sep 2011, 6:36 AM
1) How can I combine your code in any "initComponent"? Is posible but more dirty.

I do lots of things within initComponent like specify any items or dockedItems so not sure why this is "dirty". In fact I would do something like this:


initComponent: function() {
var me = this;

Ext.apply(me, {
items : me.buildItems()
}, me.applyLocale());

me.callParent(arguments);
},

applyLocale: function() {
return {
title : manager.get('titles.test', 'Test Title')
};
}


2) How can I change language dinamically?

In any JS locale, I don't see a way to do it without rerendering things.

galdaka
6 Sep 2011, 11:10 AM
I do lots of things within initComponent like specify any items or dockedItems so not sure why this is "dirty". In fact I would do something like this:


initComponent: function() {
var me = this;

Ext.apply(me, {
items : me.buildItems()
}, me.applyLocale());

me.callParent(arguments);
},

applyLocale: function() {
return {
title : manager.get('titles.test', 'Test Title')
};
}



In any JS locale, I don't see a way to do it without rerendering things.

If I create viewport regions in "Initcomponent" I can not defer literal "setters" in your "applyLoacle" function.

Initcomponent:

1) Create regions.
2) Ext.apply...
3) this.callParent(arguments)

I need set literals from locale in 1) and I think is not posible....

P.D: Sorry for my English.

mitchellsimoens
6 Sep 2011, 11:15 AM
So do two steps... first to set the locales and second to build items.

I'm not trying to be stubborn, I just don't agree with the "dirtiness" and don't see a need to hook into Ext.Loader that probably won't be there in production as it's a development tool.

galdaka
7 Sep 2011, 2:51 AM
Ext.define('Ext.app.MainViewport', {

extend: 'Ext.container.Viewport',

initComponent: function () {

Ext.app.locale.LocaleManager.setConfig({
language : 'es',
ns : 'locale',
path : '../locale'
});

Ext.app.locale.LocaleManager.loadLocale(this.applyLanguage);

var northRegion = {
xtype: 'container',
region: 'north',
width: 400,
layout: {
type: 'hbox',
padding: '1',
pack: 'end',
align: 'top'
},
items: [{
xtype: 'buttongroup',
columns: 3,
items: [{
xtype: 'button',
text: 'Galdaka', //NEED LOCALE TEXT HERE!!
align: 'middle',
autoWidth: true,
iconCls: 'user',
menu: [{
text: 'Login...', //NEED LOCALE TEXT HERE!!
iconCls: 'login',
handler: Ext.bind(this.msg, this)
}, {
text: 'Logout', //NEED LOCALE TEXT HERE!!
iconCls: 'logout',
handler: Ext.bind(this.msg, this)
}]
}]
}]
};


var centerRegion = {
xtype: 'container',
region: 'center',
layout: 'border',
defaults: {
split: true
},
border: false,
items: [{
id: 'app-container',
title: 'Aplicaciones', //NEED LOCALE TEXT HERE!!
region: 'west',
hidden: true,
animCollapse: true,
collapsible: true,
width: 200,
stateful: false,
minWidth: 150,
maxWidth: 400,
layout: 'accordion',
layoutConfig: {
animate: true
}
}, {
id: 'app-center-container',
xtype: 'tabpanel',
region: 'center',
resizeTabs: true,
enableTabScroll: true,
items: [{
xtype: 'portalpanel',
title: 'Inicio', //NEED LOCALE TEXT HERE!!
iconCls: 'home',
items: [{
id: 'col-1',
items: [{
id: 'portlet-1',
height: 200,
title: 'Donaciones ExtJS', //NEED LOCALE TEXT HERE!!
html: '<div>sfdfdfd</div>'
}]
},{
id: 'col-2',
items: [{
id: 'portlet-3',
height: 140,
title: 'Currículum', //NEED LOCALE TEXT HERE!!
html: '<div>sfdfdfd</div>'
}]
}]
}],
listeners: {
tabchange: Ext.bind(this.expandAppTree, this)
}
}]
};


Ext.apply(this, {
id: 'appMainViewport',
layout: {
type: 'border',
},
items: [northRegion, centerRegion]
}
);
},

applyLanguage: function(manager){
alert(manager.get('buttons.action'))
}

....




I don´t understand. Where is the secuence of call for make translation in this case?

You can view that I need "literals" in definition step...

____>>

Originally managed your component was focused your locale files.

I think it is important to the process of loading the file locale. And it's great how you did.

But to do half the work that remains: You must assign the literal charged the least intrusive way possible for the ExtJS code.

A synchronous load would make things easier ...

Thanks and grettings,

mitchellsimoens
7 Sep 2011, 4:43 AM
Ok, I can make a sync XHR call (well, have option too).

galdaka
7 Sep 2011, 7:16 AM
Ok, I can make a sync XHR call (well, have option too).

Hey thanks. I hope your news for implement in my web!!!

mitchellsimoens
7 Sep 2011, 10:36 AM
Hey thanks. I hope your news for implement in my web!!!

After reading some code (Connection.js in particular) I found out that Ext.Ajax.request now support sync requests. It defaults to async but you can make a sync call like this:


Ext.Ajax.request({
method : 'POST',
url : 'something.php',
async : false
});

So Ext.LocaleManager already supports sync calls!


Ext.LocaleManager.setConfig({
ajaxConfig : {
method : 'GET',
async : false
},
language : 'es',
path : 'locale.php',
type : 'ajax'
});

I have updated the ajax demo to be sync. In the PHP file, I sleep the script for 5 seconds and added a console.log after the load method on Ext.LocaleManager fires. If that echos out right away, it should be async. If it does it after the callback, it is sync. Just tested, and it was last thing to echo out in the console.

galdaka
7 Sep 2011, 1:05 PM
Sorry. I tested and not work for me...


Ext.define('Ext.app.MainViewport', {

extend: 'Ext.container.Viewport',

initComponent: function () {

Ext.app.locale.LocaleManager.setConfig({
language : 'gb',
ns : 'locale',
path : '../locale',
async : false
});

alert(111);

Ext.app.locale.LocaleManager.loadLocale(function(manager){
alert('Loaded!!!');
});

alert(222);

var northCenterRegion = {
xtype: 'container',
region: 'center',
layout: {
....
...

And the secuence is:

1) "111"
2) "222"
3) "Loaded!!!"

Other question: How can access "manager" in "initComponent" when sync call works?

Thanks in advance,

mitchellsimoens
7 Sep 2011, 1:13 PM
You didn't set up the LocaleManager correctly... there is a special Object to configure the Ext.Ajax.request:


Ext.LocaleManager.setConfig({
ajaxConfig : {
method : 'GET',
async : false
},
language : 'es',
ns : 'locale',
path : 'locale.php',
type : 'ajax'
});

galdaka
7 Sep 2011, 1:31 PM
You didn't set up the LocaleManager correctly... there is a special Object to configure the Ext.Ajax.request:


Ext.LocaleManager.setConfig({
ajaxConfig : {
method : 'GET',
async : false
},
language : 'es',
ns : 'locale',
path : 'locale.php',
type : 'ajax'
});

I suposse that solution only not works in 'loadScriptTag' mode, only in "loadAjaxRequest" mode.

Is posible "sync" in "loadScriptTag" mode? I not use "loadAjaxRequest" mode? I prefer server side out solution...

mitchellsimoens
7 Sep 2011, 1:35 PM
Loading script tags after the fact isn't going to be sync. You would have to do a sync Ajax call to the JS file. Unless you know of a way to load a script tag sync

galdaka
7 Sep 2011, 1:46 PM
Loading script tags after the fact isn't going to be sync. You would have to do a sync Ajax call to the JS file. Unless you know of a way to load a script tag sync

Would be posible load json file in "loadAjaxRequest" and separate locale managment of server side language. What do you think?

mitchellsimoens
7 Sep 2011, 1:51 PM
If you want locale to be sync... the only way I see to do it is via Ajax

galdaka
8 Sep 2011, 7:58 AM
If you want locale to be sync... the only way I see to do it is via Ajax

Done. You can view in action in: www.jadacosta.es

[/URL]I use JSON locale files and work fine!
[URL="http://www.jadacosta.es"]
T (http://www.jadacosta.es)hanks for your help!!

mitchellsimoens
8 Sep 2011, 9:42 AM
Seems to work great! Fantastic! Keep suggestions coming! Or you can fork the GitHub repo and do pull requests :)

galdaka
8 Sep 2011, 11:14 AM
Only one suggestion. I would add specific configutation in your component if you want load JSON files intead JS files. Now I use this configuraton:


lm.setConfig({
ajaxConfig : {
method : 'GET',
async : false
},
path : lParam ? 'locale/locale_' + lParam + '.js' : 'locale/locale_es.js',
type : 'ajax'
});

Would be great if I could use this one:


lm.setConfig({
ajaxConfig : {
method : 'GET',
async : false
},
path : '/locale',
type : 'ajax',
language: lParam
});

In "loadAjaxRequest" mode you can´t define "language" and "file" type mode.

I think would be more clean.

Thanks and greetings,

koblass
9 Sep 2011, 7:58 AM
Hi,

What would be very nice is the ability to dynamically change the locale without any need to restart the application.

The idea of having a Ext.LocaleManager is great, but this manager should have a "change" event that is raised when the locale is changed. This LocaleManager should also provide methods methods in order to retrieved and set locale.

Like this every component would be able to add an event listener to the "change" event on the LocaleManager and then change its translation.

An instance of the LocaleManager should by created by default by the app, so like this all the ExtJs components that require translation (like datePicker) could be translated automatically, but we should keep in mind to be able to have multiple LocaleManager instances inside of our application in order to avoid key collision.

This is definitely something that has to be added in ExtJs if we want to be able to dynamically change the locale of the application, which is a must have !

Best
Daniel

mitchellsimoens
9 Sep 2011, 8:01 AM
I have been brainstorming about this but I am worried about performance but I think I have something that may work at least.

koblass
9 Sep 2011, 8:44 AM
Hi Mitchell,

I've bee working like this for years now with an other framework (bindows, not to mention), and they have a great BiStringBundle component that does the work.

Performances are not an issue at all and switching from one language to another is just instantaneous.
The only thing to keep in mind is to keep string bundles (locale dictionary) not too big, that's why we need to be able to create as many StringBundles or LocaleBundle as needed.

If I would do the component myself I would do it like this :

One Ext.LocaleManager which is a singleton. This LocaleManager is just in charge of keeping track of the loaded locale (language / country codes) and raising the "change" event when the locale changes.

Then have a StringBundle class or LocaleBundle, that is just a dictionary key/value, with a set of useful methods, like getString or getFormattedString (same thing, but with parameters)

The LocaleManager should have a collection o LocaleBundle that can be accessed by a getter and setter method.

Like this it would be easy to have something like this :



Ext.LocaleManager.get('Ext') // This will return the LocaleBundle stored under the "Ext" key

Ext.LocaleManager.addEventListener("change", ..... ); // The method will be called when the locale changes

// Be able to do the same directly on the LocaleBundle
Ext.LocaleManager.get('Ext').addEventListener("change", ..... );

// To store a new LocaleBundle
Ext.LocaleManager.add('myKey', new Ext.LocaleBundle(...));


The LocaleManager should also raise an event when we try to access to a LocaleBundle that is not loaded/defined. Like this, we can easily handle the loading of the LocaleBundle. Ideally a proxy should by defined in the LocaleManager, which would be in charge of loading the LocaleBundle from the server. Of course this proxy could be replaced in order to fit everybody's needs.


Hope to have helped you with this input and if you need any feedback, I would be happy to help.

Best
Daniel

mitchellsimoens
10 Sep 2011, 5:36 AM
What do you mean a "bundle"? Like using the getter, it will return an Object of locale strings?

Using events is something that I hadn't thought of, amazingly. So the Component adds a change event and when fired, updates all the Component's things that need locale?

koblass
12 Sep 2011, 1:28 AM
Hi Mitchell,

For be a bundle is just a dictionary component that provide a "change" event and two methods "getString" and "getFormattedString" (same method as getString, but takes parameters for injections within the translated string)

That's exactly how it works ! Events are fired and the components refresh their translations.

One important thing, is that the translation loading needs to be "on demand".
In order to perform this the LocaleManager is in charge of creating the LocaleBundle when requested and load asynchronously the translation regarding the locale. During this phase (when the translations are not loaded), the "getString" and "getFormattedString" method of the LocaleBundle return a default text (that should be present in the main LocalBundle for instance), like "Loading...". Then when the content of the LocaleBundle is loaded the "change" event should also be fired on this LocaleBundle object, so that the components who access to those translations can update themselves.

I thought a little bit about it this week end, and I think that we definitely need to have a proxy and a reader (a little bit like for the data package). Like this we can personalize the way the translations are received (use a webservice/json-rpc, etc...), and the way they are formatted (ini, json, etc...)

So basically, we should have 4 distinct classes. A Ext.LocaleManager, Ext.LocaleBundle, Ext.LocaleProxy and Ext.LocaleReader. (change the names accordingly of course)

Best regards
Daniel

vadimv
12 Sep 2011, 3:39 AM
Hi,

What would be very nice is the ability to dynamically change the locale without any need to restart the application.

Daniel

+1, would be great.

mitchellsimoens
12 Sep 2011, 5:05 AM
Thank you for explaining... this got the creative juices flowing :)


One important thing, is that the translation loading needs to be "on demand".
In order to perform this the LocaleManager is in charge of creating the LocaleBundle when requested and load asynchronously the translation regarding the locale. During this phase (when the translations are not loaded), the "getString" and "getFormattedString" method of the LocaleBundle return a default text (that should be present in the main LocalBundle for instance), like "Loading...". Then when the content of the LocaleBundle is loaded the "change" event should also be fired on this LocaleBundle object, so that the components who access to those translations can update themselves.

Not sure I like having the text "Loading...", I think having the default (or user pref specified) locale text there at app startup is the correct way to do this. For web applications, you really shouldn't need to reload locale often. 90% of the time, it will be on default and the only time it will change is if the user selects to change it. After that it should be saved in user preferences. Web sites you would need to but that's not really what Ext JS (or my mindset) is geared towards.


So basically, we should have 4 distinct classes. A Ext.LocaleManager, Ext.LocaleBundle, Ext.LocaleProxy and Ext.LocaleReader. (change the names accordingly of course)

Agree with Ext.LocaleManger and Ext.LocaleBundle but I'm not sure a special proxy and reader are needed. That's another can of worms on trying to make something that works for many use cases. I would rather leave that part up to the individual devs to create but I do agree that Ext.LocaleManger should be more aligned with the data package.

koblass
12 Sep 2011, 5:48 AM
Hi Mitchell




Not sure I like having the text "Loading...", I think having the default (or user pref specified) locale text there at app startup is the correct way to do this. For web applications, you really shouldn't need to reload locale often. 90% of the time, it will be on default and the only time it will change is if the user selects to change it. After that it should be saved in user preferences. Web sites you would need to but that's not really what Ext JS (or my mindset) is geared towards.

I don't agree with you on this point :-)
I do agree on the fact that the users rarely change the language of the app, but what is the default translation ? The English one, the French one, the... ?!?!
Of course I could load the translation file regarding the user profile at start up of the app, but this is ok for small apps... What about modular apps that loads portion of code (portion of the app) dynamically ? In this case you'll also have to load the translations dynamically and in this case the "default" translation will have to be in a chosen language, which generally is English. As a final user, I rather prefer to have a "Loading..." text everywhere for half a second and then the translated labels in my language.
But why not having the two options ? The second parameter of the getString method could be the "default" text and/or this could be configured in the main LocaleBundle (I don't like the idea of having it as a config option, because once again this won't be localized...




Agree with Ext.LocaleManger and Ext.LocaleBundle but I'm not sure a special proxy and reader are needed. That's another can of worms on trying to make something that works for many use cases. I would rather leave that part up to the individual devs to create but I do agree that Ext.LocaleManger should be more aligned with the data package.

The problem there is that the LocaleManager will be in charge of loading the LocaleBundle on demand. So the LocaleManager has to know how to load the data/translations from the backend, so a proxy will be required there... And if we have a proxy there, why not having a reader that would give more flexibility or the data representation ? Could by nice to be able to load ini files or json files directly from the server for instance...

Best regards
Daniel

mitchellsimoens
12 Sep 2011, 6:00 AM
I don't agree with you on this point :-)
I do agree on the fact that the users rarely change the language of the app, but what is the default translation ? The English one, the French one, the... ?!?!
Of course I could load the translation file regarding the user profile at start up of the app, but this is ok for small apps... What about modular apps that loads portion of code (portion of the app) dynamically ? In this case you'll also have to load the translations dynamically and in this case the "default" translation will have to be in a chosen language, which generally is English. As a final user, I rather prefer to have a "Loading..." text everywhere for half a second and then the translated labels in my language.
But why not having the two options ? The second parameter of the getString method could be the "default" text and/or this could be configured in the main LocaleBundle (I don't like the idea of having it as a config option, because once again this won't be localized...

It's ok to disagree... discussion will only bring all sides to the table to make something better than one of us could make. Default language is whatever the developer sets the initial language too. Some people can set the language to English, some to French. About modular apps... currently not supported within Ext JS 4 so therefor I cannot guess how we will be doing it so I don't want to put forth effort on something that I would probably have to change later. I currently have default text as an option in the get method and will be keeping this no matter what direction this manager goes.


The problem there is that the LocaleManager will be in charge of loading the LocaleBundle on demand. So the LocaleManager has to know how to load the data/translations from the backend, so a proxy will be required there... And if we have a proxy there, why not having a reader that would give more flexibility or the data representation ? Could by nice to be able to load ini files or json files directly from the server for instance...

Ext.LocaleManager will have it's own "API" of sorts... will publish the fields it needs and then you can create your proxy/reader to adhere. Working at Fortune 100 clients, you don't really have a say on what the data looks like. The TreePanel is a great example, very rarely do I get the text and leaf that I need, I always have to hook into processResponse to change the incoming JSON/XML into what the TreePanel/TreeLoader needs. So I see it being that people will override the proxy/reader to use their own and do mapping or convert or whatever they need.

koblass
12 Sep 2011, 6:23 AM
Default language is whatever the developer sets the initial language too. Some people can set the language to English, some to French. About modular apps... currently not supported within Ext JS 4 so therefor I cannot guess how we will be doing it so I don't want to put forth effort on something that I would probably have to change later. I currently have default text as an option in the get method and will be keeping this no matter what direction this manager goes.

Well, sound ok to me, but could it be possible to define a global default translation if no default translation have been added to the get method ? Like this our two options could coexist :-)



Ext.LocaleManager will have it's own "API" of sorts... will publish the fields it needs and then you can create your proxy/reader to adhere. Working at Fortune 100 clients, you don't really have a say on what the data looks like. The TreePanel is a great example, very rarely do I get the text and leaf that I need, I always have to hook into processResponse to change the incoming JSON/XML into what the TreePanel/TreeLoader needs. So I see it being that people will override the proxy/reader to use their own and do mapping or convert or whatever they need.

Sounds good to me too to use a processResponse method that you can overwrite.

I'm very excited to be able to test your solution :-)

Best
Daniel

mitchellsimoens
12 Sep 2011, 6:28 AM
Well, sound ok to me, but could it be possible to define a global default translation if no default translation have been added to the get method ? Like this our two options could coexist :-)

By default, Ext.LocaleManager will default to English. You will have a way to set a default language in the app. You will also have the option to specify default text in the get method (just in case server goes down or that particular locale isn't in the database).

koblass
12 Sep 2011, 6:41 AM
By default, Ext.LocaleManager will default to English. You will have a way to set a default language in the app. You will also have the option to specify default text in the get method (just in case server goes down or that particular locale isn't in the database).

I think that this solution is just perfect.

I've just one question in mind right now...
- As we can define "default" translations as a second parameter to the get method. Let say this default translation for my app is in English. Then loading a locale file for this translation is not needed, how do you plan to handle this ?

Best
Daniel

mitchellsimoens
12 Sep 2011, 6:50 AM
I think that this solution is just perfect.

I've just one question in mind right now...
- As we can define "default" translations as a second parameter to the get method. Let say this default translation for my app is in English. Then loading a locale file for this translation is not needed, how do you plan to handle this ?

I try not to require too many things. Default text should only be used for error handling (load fails) but if someone doesn't want to load a bundle for the default language, their option. I will say, it is much easier to manage and scale if you keep all locales in the same spot, a database (or however you store it) instead of hunting through your JS code to change default text.

koblass
12 Sep 2011, 7:07 AM
I try not to require too many things. Default text should only be used for error handling (load fails) but if someone doesn't want to load a bundle for the default language, their option. I will say, it is much easier to manage and scale if you keep all locales in the same spot, a database (or however you store it) instead of hunting through your JS code to change default text.

I agree once again, but would it be then possible to have more events, like "beforeload" and "load" on the LocaleManager ? The "beforeload" event could do the trick if needed as it could be canceled and then the locale resource wouldn't be loaded. So the problem could be solved if require...

What do you think ?

Best
Daniel

mitchellsimoens
12 Sep 2011, 7:13 AM
What do you think ?

Already ahead of you :) At a client location during day so won't be able to work on my/our ideas till evenings.

SnakeMedia
16 Sep 2011, 5:41 AM
Great Job, but i see different like Qooxdoo and Extjs :)

Extjs:
Need part of locale java script files like:
lang_de is German's Version
lang_en is English's Version
/MyApp
../locales/lang_<country>.js

For Qooxdoo:
/MyApp
../translation/myapp_<country>.js

But i find because implement is not sure for me. Please change to like this:
Code:
this.tr(<Instance Name>.text = "Hello World");
it is very better than localeManager by Extjs :(.

I find Translation / Location by Qooxdoo because it is stability.

Look at Qooxdoo and Extjs are different for Translation and Location:
http://manual.qooxdoo.org/1.4.x/pages/tutorials/tutorial-part-4-3.html

A (http://manual.qooxdoo.org/1.4.x/pages/tutorials/tutorial-part-4-3.html)nd Example for Qooxdoo: http://demo.qooxdoo.org/current/showcase/#i18n

F (http://demo.qooxdoo.org/current/showcase/#i18n)or Extjs:
Example: http://dev.sencha.com/deploy/ext-4.0.2a/examples/locale/dutch-form.html

S (http://dev.sencha.com/deploy/ext-4.0.2a/examples/locale/dutch-form.html)o waht is framework different?
Implement for Qooxdoo is better than Extjs :( Please improve again!
this.tr(); = better than Extjs's Code :(


Ext.LocaleManager.get('Ext') // This will return the LocaleBundle stored under the "Ext" key
Ext.LocaleManager.addEventListener("change", ..... ); // The method will be called when the locale changes// Be able to do the same directly on the LocaleBundleExt.LocaleManager.get('Ext').addEventListener("change", ..... );// To store a new LocaleBundleExt.LocaleManager.add('myKey', new Ext.LocaleBundle(...));I hope your location and translation while you make sure :)

Thanks :)

mitchellsimoens
16 Sep 2011, 5:59 AM
Already been discussed. I don't develop based on what other frameworks are doing.

Also, this is not part of the framework... it's a 3rd party extension even tho I work for Sencha.

koblass
16 Sep 2011, 6:17 AM
Fully agree with Mitchell,

Moreover the qooxdoo solution is not very nice because you need to run a translations generator which is not always possible for modular applications.

If you really like the "this.tr" solution you can always overwrite the Ext.Component in order to add this method...


Mitchell, as you work for Sencha, do you think that a general solution for handling Locales is in the pipeline ?
My concern is that, we can easily develop a way to manage the translation of the entire application, even reload dynamically the Locale files in order to overwrite the components, but then we should be able to re-render those components if we want the changes to be applied (like for the date picker for instance). Would be nice to have a sencha's defined way of doing it...

Best
Daniel

mitchellsimoens
16 Sep 2011, 6:24 AM
Mitchell, as you work for Sencha, do you think that a general solution for handling Locales is in the pipeline ?
My concern is that, we can easily develop a way to manage the translation of the entire application, even reload dynamically the Locale files in order to overwrite the components, but then we should be able to re-render those components if we want the changes to be applied (like for the date picker for instance). Would be nice to have a sencha's defined way of doing it...

To be honest... performance is out main concern in 4.1. Will we do something... hopefully :)

SnakeMedia
19 Sep 2011, 5:19 AM
Yeah you are rights...

I find you say becasue qooxdoo isn't nice. I know because Extjs is better than Qooxdoo :)

Okay.. i will learn with Extjs :) Thanks for solution!

Regards, SnakeMedia