Re: [Zope3-Users] configure access from zcml
On Wed, Feb 21, 2007 at 11:04:26AM +0100, Michael Haubenwallner wrote: The publication requestfactories are available by default. Is there a way to configure protocol access to the whole site, local sites, containers or objects through ZCML ? How would a sysadmin e.g. enable xmlrpc access to the site or a folder only or disable xmlrpc access to a certain object or interface ? I'm not completely sure, but perhaps you can override the traverse zcml directives in zope/app/publisher/xmlrpc/configure.zcml Tim ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Events
Does anyone know the process by which objects are notified by events? I created a custom container that stores objects in MySQL. However, I noticed that when I add a container that an ObjectAddedEvent is then propogated to every single object in my container, generating nearly 2000 queries. From my reading of the core Zope code, it seems that when an event is triggered it is sent to every single object in every container. This seems rather inefficient if you have either a large container or large objects in your container. Am I understanding this correctly? None of my objects subscribe to events (at least not yet). The problem seems to start in zope.app.container.contained.sublocations, which basically queries all objects in a container and sends an event to all of them. excerpt from zope.app.container.contained.ContainerSublocations: def sublocations(self): container = self.container for key in container: yield container[key] Warm regards, David ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: Events
David Johnson wrote: Does anyone know the process by which objects are notified by events? Objects aren't typically notified of events. Event handlers are. The whole event setup, including object events, is explained in detail in my book, http://worldcookery.com. I suggest picking up a copy :) I created a custom container that stores objects in MySQL. However, I noticed that when I add a container that an ObjectAddedEvent is then propogated to every single object in my container, generating nearly 2000 queries. From my reading of the core Zope code, it seems that when an event is triggered it is sent to every single object in every container. This seems rather inefficient if you have either a large container or large objects in your container. Am I understanding this correctly? To a degree. A common pattern in Zope is event dispatch. Dispatchers receive an event and propapage it further. The container machinery has such a dispatcher for ObjectMovedEvents. When a container is moved, it propapates the event to its subobjects, so they know their overall physical location has changed. An ObjectAddedEvent is a special case of ObjectMovedEvent. The problem seems to start in zope.app.container.contained.sublocations, which basically queries all objects in a container and sends an event to all of them. You're probably talking about dispatchToSublocations. This is the code that looks up a containers sublocations and dispatches the event to them. One way to prevent this behaviour for your container is to write a new ISublocations adapter for your container that simply returns an empty sequence: class MyContainerSublocations(object): implements(zope.location.interfaces.ISublocations) adapts(...IMyContainer) def __init__(self, context): self.context = context def sublocations(self): return () -- http://worldcookery.com -- Professional Zope documentation and training Next Zope 3 training at Camp5: http://trizpug.org/boot-camp/camp5 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: Events
You're probably talking about dispatchToSublocations. This is the code that looks up a containers sublocations and dispatches the event to them. One way to prevent this behaviour for your container is to write a new ISublocations adapter for your container that simply returns an empty sequence: class MyContainerSublocations(object): implements(zope.location.interfaces.ISublocations) adapts(...IMyContainer) def __init__(self, context): self.context = context def sublocations(self): return () This is probably the approach I will follow, but what if I want my container objects notified? Even if I don't it seems the default Folder implementation follows this logic and so if you have a folder with several large images for example, then you will pay a price whenever an event is issued. In general it seems that any change will result in the entire ZODB being read for each event dispatch...if I still follow the logic here. -- David ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: Events
On 22 Feb 2007, at 13:37 , David Johnson wrote: You're probably talking about dispatchToSublocations. This is the code that looks up a containers sublocations and dispatches the event to them. One way to prevent this behaviour for your container is to write a new ISublocations adapter for your container that simply returns an empty sequence: class MyContainerSublocations(object): implements(zope.location.interfaces.ISublocations) adapts(...IMyContainer) def __init__(self, context): self.context = context def sublocations(self): return () This is probably the approach I will follow, but what if I want my container objects notified? I thought you don't... ? Even if I don't it seems the default Folder implementation follows this logic and so if you have a folder with several large images for example, then you will pay a price whenever an event is issued. In general it seems that any change will result in the entire ZODB being read for each event dispatch...if I still follow the logic here. That's not what I said. It will only happen on object moves, in particular, when a container is moved. It will also only happen for the subitems of that container, not the whole ZODB, though arguably that can mean a lot of data. I would personally like to see some form of disabling event handlers. ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: Events
On 22 Feb 2007, at 14:57 , David Johnson wrote: This is probably the approach I will follow, but what if I want my container objects notified? I thought you don't... ? This is both a theory and practice question. I want to make sure I follow practices that will not lead me into trouble in the future. In this case I am likely to want an ObjectModifiedEvent so that my objects can be saved if they are modified. For example if I edit an object via browser:editform, an ObjectModifiedEvent will be sent. I am not clear whether Zope will examine every object in my container to see if it has an event handler for ObjectModifiedEvent; which is what it seems to do now. You still don't seem to be getting it. The dispatching to container subobjects only happens for Object*Moved*Events, not on ObjectModifiedEvents or any other events. Also, objects don't have event handlers. There is a certain class of events called object events. Code that does something to objects (create them, add the to a container, modify them, etc.) is supposed to send events about this. Then there aree event handlers that react to this. The original object is completely unaware of both the fact that an event is being sent about it and the fact that event handlers react to this. And that's exactly the beauty of it. Events let you implement business logic completely outside of the data model. For further understanding, I really do suggest reading my book, it's explained in detail there. Any further discussion w/o that background will likely end up in confusion. ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] translation domains and their scope
Hello, I am having some trouble with translation domains. I have setup two for use. Call one 'common' and the other 'myapp'. They were created under a folder that was turned into a site using the ZMI. Call this site MYSITE. The translation domains were also registered via the ZMI. I have filled in various message ids and their translations for en and fr in each domain. I have also made sure to use the proper i18n:domain declarations, as appropriate. For locations under MYSITE, the myapp and common translations work well (within a generic browser page template configured for ISite): i.e. http://localhost:8080/MYSITE/ However, using http://localhost:8080/ to display the same generic page (as another ISite), the translations do not happen. I want to use the 'common' translation domain (TD) across more than one site (i.e. the use case above would allow me to have a splash page at the site root using common translations with a choice among subsites). So, thinking I should move the 'common' TD to the zope instance root I use the ZMI cut and paste functions to move the 'common' domain from MYSITE to the root/global(?) site. I also checked, unregistered, and registered where appropriate. Now the translations for common, formerly functional under MYSITE, no longer work under MYSITE, nor do they work under the root site, nor anywhere else. What gives? Is there something bad about using cut and paste to move a translation domain? How are translation domains looked up and used? What are their scopes? Also, What is the relationship, if any, between the name used in the registration (as shown below) and the name of the translation domain 'common'? (I did add text to the 'Register as' input box when I re-registered the 'common' TD.) This object is registered: zope.app.i18n.interfaces.ILocalTranslationDomain utility named 'Common Look and Feel' Thanks for shedding some light on how a site and a translation domain inter-relate. Mark ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
RE: [Zope3-Users] Events
Hello David, Does anyone know the process by which objects are notified by events? I created a custom container that stores objects in MySQL. However, I noticed that when I add a container that an ObjectAddedEvent is then propogated to every single object in my container, generating nearly 2000 queries. From my reading of the core Zope code, it seems that when an event is triggered it is sent to every single object in every container. This seems rather inefficient if you have either a large container or large objects in your container. Am I understanding this correctly? None of my objects subscribe to events (at least not yet). I was reading about this stuff (source code) last night. Perhaps this might help. The file location is, of course, system dependent. From: /usr/local/www/Zope3/lib/python/zope/app/container/interfaces.py class IWriteContainer(Interface): An interface for the write aspects of a container. def __setitem__(name, object): Add the given `object` to the container under the given name. [snip]... If the object's `__parent__` and `__name__` were already set to the container and the name, then no events are generated and no hooks. This allows advanced clients to take over event generation. Mark ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] User preferences for languages- possible?
Hi, This stuff is crazy. I just want to implement a user preference for a language (because I have to). I've read all the user pref. documentation (skinpref, apidoc prefs and zope.app.preference) until I'm blue in the face. Nothing seems to work and there is no help via google and so forth. I know that UserPreferences() wants an ILocation object. I can't seem to get one inside the BrowserFormLanguages class. I am only given the request object. What do I need to do? Getting a root site is insane the way I found to do it via a mailing list message. Not to mention it had issues racking up db connections, then failing on close. Help! Please! Thank you! Preferences seem to work since I can edit them using the http://.../++preferences++/ form. Mark P.S. This is not covered in Richter's book, nor von Weitershausen's (1st ed.) both of which I bought. Experimental code and traceback follow: === 8=== language.py === from zope.interface import implements from zope.component import adapts from zope.publisher.interfaces.browser import IBrowserRequest from zope.i18n.interfaces import IUserPreferredLanguages from zope.i18n.interfaces import IModifiableUserPreferredLanguages from zope.app.session.interfaces import IClientId from zope.publisher.browser import BrowserLanguages from zope.app.component.hooks import setSite, getSite from zope.app.preference.interfaces import IUserPreferences from zope.app.preference import UserPreferences #import ZODB #from zope.component import getUtility class BrowserFormLanguages(BrowserLanguages): implements(IModifiableUserPreferredLanguages) language_store = [] # ignore this for now def __init__(self, request): super(BrowserFormLanguages, self).__init__(request) print created BFL, self.language_store def setPreferredLanguages(self, langs): #prefs = UserPreferences() #print prefs.eods.general.language self.language_store = langs print set language, self.language_store def getPreferredLanguages(self): langs = super(BrowserFormLanguages, self).getPreferredLanguages() if self.language_store: langs = self.language_store + langs form_lang = self.request.get(Language, None) if form_lang is not None: langs.insert(0, form_lang) #this just leads to madness and a horrible error #[...] exceptions.ValueError: I/O operation on closed file #db = getUtility(ZODB.interfaces.IDatabase) #conn = db.open() #root = conn.root().data['Application'] #setSite(root) #prefs = UserPreferences(getSite()) prefs = UserPreferences() print Prefs, repr(prefs) #print repr(getSite()) print prefs.__dict__ # crashes on the next line - but prints the word lang print lang, prefs.eods.general.language print My prefered override, langs #db.close() return langs == Traceback: == created BFL [] Prefs zope.app.preference.preference.PreferenceGroup object at 0x963466c {'__schema__': None, '__Security_checker__': zope.security.checker.Checker object at 0xa153dec, '__description__': u'', '_PreferenceGroup__parent': BaseGlobalComponents base, '__name__': '++preferences++', '__title__': u'User Preferences', '__provides__': zope.interface.Provides object at 0x95bfe8c, '__id__': u''} lang-- 2007-02-22T15:54:50 DEBUG twisted Exception rendering: -- 2007-02-22T15:54:50 DEBUG twisted Traceback (most recent call last): File /usr/local/lib/python2.4/threading.py, line 422, in run self.__target(*self.__args, **self.__kwargs) File /usr/local/www/Zope3/lib/python/twisted/python/threadpool.py, line 149, in _worker context.call(ctx, function, *args, **kwargs) File /usr/local/www/Zope3/lib/python/twisted/python/context.py, line 59, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File /usr/local/www/Zope3/lib/python/twisted/python/context.py, line 37, in callWithContext return func(*args,**kw) --- exception caught here --- File /usr/local/www/Zope3/lib/python/twisted/web2/wsgi.py, line 139, in run result = self.application(self.environment, self.startWSGIResponse) File /usr/local/www/Zope3/lib/python/zope/app/wsgi/__init__.py, line 50, in __call__ request = self.requestFactory(environ['wsgi.input'], environ) File /usr/local/www/Zope3/lib/python/zope/app/publication/httpfactory.py, line 69, in __call__ request = request_class(input_stream, env) File /usr/local/www/Zope3/lib/python/zope/publisher/browser.py, line 229, in __init__ super(BrowserRequest, self).__init__(body_instream, environ, response) File /usr/local/www/Zope3/lib/python/zope/publisher/http.py, line 323, in __init__ self.setupLocale() File /usr/local/www/Zope3/lib/python/zope/publisher/http.py, line 331, in
[Zope3-Users] Re: User preferences for languages- possible?
Giovannetti, Mark wrote: Hi, This stuff is crazy. I just want to implement a user preference for a language (because I have to). I've read all the user pref. documentation (skinpref, apidoc prefs and zope.app.preference) until I'm blue in the face. Nothing seems to work and there is no help via google and so forth. I know that UserPreferences() wants an ILocation object. I can't seem to get one inside the BrowserFormLanguages class. I am only given the request object. What do I need to do? Getting a root site is insane the way I found to do it via a mailing list message. Not to mention it had issues racking up db connections, then failing on close. Help! Please! Thank you! Preferences seem to work since I can edit them using the http://.../++preferences++/ form. The zope.app.preference stuff stores the info in principal annotations, in a weird way. I personally find that stuff a bit convoluted. The key, as you've correctly identified, is write your own IUserPreferredLanguages adapter (or a variant thereof). I would store the user's preferences in a cookie or a session. This makes things much easier. Simply adapt the request to ISession(request). Note that this might not always work, e.g. when the request is instantiated and the request's locale is first created (because local utilities to store the session data in aren't available at that point). It seems you're hitting that exact problem with the preference stuff as well. The trick here is to stub this out when the adapter is first called, and then later during traversal, when you know the local components are there, you revisit it all again by calling request.setUpLocale() or whatever it is. The ++lang++ implementation might give some pointers. -- http://worldcookery.com -- Professional Zope documentation and training Next Zope 3 training at Camp5: http://trizpug.org/boot-camp/camp5 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: translation domains and their scope
Giovannetti, Mark wrote: Hello, I am having some trouble with translation domains. I have setup two for use. Call one 'common' and the other 'myapp'. They were created under a folder that was turned into a site using the ZMI. Call this site MYSITE. The translation domains were also registered via the ZMI. I have filled in various message ids and their translations for en and fr in each domain. I have also made sure to use the proper i18n:domain declarations, as appropriate. For locations under MYSITE, the myapp and common translations work well (within a generic browser page template configured for ISite): i.e. http://localhost:8080/MYSITE/ However, using http://localhost:8080/ to display the same generic page (as another ISite), the translations do not happen. I want to use the 'common' translation domain (TD) across more than one site (i.e. the use case above would allow me to have a splash page at the site root using common translations with a choice among subsites). So, thinking I should move the 'common' TD to the zope instance root I use the ZMI cut and paste functions to move the 'common' domain from MYSITE to the root/global(?) site. I also checked, unregistered, and registered where appropriate. Now the translations for common, formerly functional under MYSITE, no longer work under MYSITE, nor do they work under the root site, nor anywhere else. What gives? Is there something bad about using cut and paste to move a translation domain? How are translation domains looked up and used? What are their scopes? The scope of any local utility (and that includes translation domains) is the site that it was registered for. It's therefore not surprising that a translation domain you added and registered in MYSITE are not available outside that folder. Why aren't you going for global translation domains that are maintained as gettext PO files on the filesystem and registered using ZCML? My book (also the 1st edition) explains how to do that. -- http://worldcookery.com -- Professional Zope documentation and training Next Zope 3 training at Camp5: http://trizpug.org/boot-camp/camp5 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] RE: translation domains and their scope
Hi Philipp, Thanks for responding. I am including the mailing list. From: Philipp von Weitershausen [mailto:[EMAIL PROTECTED] Giovannetti, Mark wrote: [snip] However, using http://localhost:8080/ to display the same generic page (as another ISite), the translations do not happen. I want to use the 'common' translation domain (TD) across more than one site (i.e. the use case above would allow me to have a splash page at the site root using common translations with a choice among subsites). So, thinking I should move the 'common' TD to the zope instance root I use the ZMI cut and paste functions to move the 'common' domain from MYSITE to the root/global(?) site. I also checked, unregistered, and registered where appropriate. Now the translations for common, formerly functional under MYSITE, no longer work under MYSITE, nor do they work under the root site, nor anywhere else. What gives? Is there something bad about using cut and paste to move a translation domain? How are translation domains looked up and used? What are their scopes? The scope of any local utility (and that includes translation domains) is the site that it was registered for. It's therefore not surprising that a translation domain you added and registered in MYSITE are not available outside that folder. Ok, fair enough. That still doesn't explain why moving the 'common' TD to the [top] 'site' (in the ZMI) didn't 'globalize' it. Oh well, I guess it's just another of those unexplained head scratchers that zope3 seems to be infused with. I was under the impression that a utility that wasn't found in a local site was searched up-the-stack to the global site. Why aren't you going for global translation domains that are maintained as gettext PO files on the filesystem and registered using ZCML? My book (also the 1st edition) explains how to do that. I have reread the chapter on i18n and will try the ZCML registerTranslations directive. Does this guarantee that all translation domains registered via this directive will be available *everywhere* in the zope instance? If so then I thank you for reminding me about it. If not, wtf? I had wanted to use the GUI in the ZMI for simple testing before getting to the gettext formalization for the app. I'd also like to have the possibility of allowing clerical staff to enter immediate translations for content using the ZMI GUI but my expectations in this may not be realized. I will inform the mailing list of my progress. Thanks again. Mark ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: translation domains and their scope
On 22 Feb 2007, at 23:59 , Giovannetti, Mark wrote: From: Philipp von Weitershausen [mailto:[EMAIL PROTECTED] Giovannetti, Mark wrote: [snip] However, using http://localhost:8080/ to display the same generic page (as another ISite), the translations do not happen. I want to use the 'common' translation domain (TD) across more than one site (i.e. the use case above would allow me to have a splash page at the site root using common translations with a choice among subsites). So, thinking I should move the 'common' TD to the zope instance root I use the ZMI cut and paste functions to move the 'common' domain from MYSITE to the root/global(?) site. I also checked, unregistered, and registered where appropriate. Now the translations for common, formerly functional under MYSITE, no longer work under MYSITE, nor do they work under the root site, nor anywhere else. What gives? Is there something bad about using cut and paste to move a translation domain? How are translation domains looked up and used? What are their scopes? The scope of any local utility (and that includes translation domains) is the site that it was registered for. It's therefore not surprising that a translation domain you added and registered in MYSITE are not available outside that folder. Ok, fair enough. That still doesn't explain why moving the 'common' TD to the [top] 'site' (in the ZMI) didn't 'globalize' it. Oh well, I guess it's just another of those unexplained head scratchers that zope3 seems to be infused with. Normally this works. You simply have to make sure you unregister the translation domain as a utility, move it, and then re-register it in the root site again. Even if those steps are messed up, it should work if you remember to re-register it with the root site. I wouldn't be surprised if you simply forgot that last step. I was under the impression that a utility that wasn't found in a local site was searched up-the-stack to the global site. Yes, utilities are searched up the stack. If not found in the local- most site, then perhaps in the next site, etc, until the root site is reached. If that doesn't have it, the global registry isn't searched for. Why aren't you going for global translation domains that are maintained as gettext PO files on the filesystem and registered using ZCML? My book (also the 1st edition) explains how to do that. I have reread the chapter on i18n and will try the ZCML registerTranslations directive. Does this guarantee that all translation domains registered via this directive will be available *everywhere* in the zope instance? If so then I thank you for reminding me about it. If not, wtf? Of course they will. That's the point of global components. Next time I suggest you read the book first ;). I had wanted to use the GUI in the ZMI for simple testing before getting to the gettext formalization for the app. That's fine, though I don't find the gettext way is neither formalized nor is it particularly more complicated than the local utility stuff (well, ok, you have to compile the .po files to .mo...). In the end you're just going to have to write code to export your persistent translation domains to .po files on the filesystem... ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
RE: [Zope3-Users] Re: User preferences for languages- possible?
Hi Philipp, You are a great resource, thanks for helping. See below. From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Philipp von Weitershausen Giovannetti, Mark wrote: Hi, This stuff is crazy. I just want to implement a user preference for a language (because I have to). I've read all the user pref. documentation (skinpref, apidoc prefs and zope.app.preference) until I'm blue in the face. Nothing seems to work and there is no help via google and so forth. I know that UserPreferences() wants an ILocation object. I can't seem to get one inside the BrowserFormLanguages class. I am only given the request object. What do I need to do? Getting a root site is insane the way I found to do it via a mailing list message. Not to mention it had issues racking up db connections, then failing on close. Help! Please! Thank you! Preferences seem to work since I can edit them using the http://.../++preferences++/ form. The zope.app.preference stuff stores the info in principal annotations, in a weird way. I personally find that stuff a bit convoluted. If you find it convoluted, then how are us mere mortals supposed to deal with it? ;-) The key, as you've correctly identified, is write your own IUserPreferredLanguages adapter (or a variant thereof). I would store the user's preferences in a cookie or a session. This makes things much easier. Simply adapt the request to ISession(request). I'll end up having to do something like this, I suppose. It really sucks, though, because I *want* to use the preferences machinery. Why was it built if it can't be used in certain places - and why aren't the places it can't be used documented? Arrg. Note that this might not always work, e.g. when the request is instantiated and the request's locale is first created (because local utilities to store the session data in aren't available at that point). How am I supposed to deal with what you say above? I don't even understand most of it! ;-) It seems you're hitting that exact problem with the preference stuff as well. The trick here is to stub this out when the adapter is first called, 'stub this out ... ' - I don't understand, sorry. and then later during traversal, when you know the local components are there, you revisit it all again by calling request.setUpLocale() or whatever it is. I don't know what you mean. How is a noob supposed to deal with this? The ++lang++ implementation might give some pointers. The ++lang++ implementation (and ensuing errors when I tested using it) told me that I needed to change BrowserFormLanguages to use IModifiableUserPreferredLanguages. Since I had to do that in order to allow language preferences I decided to get the UserPreferences machinery running for the app. Now I have this problem. The *must* be a common use case. Why isn't this already solved and documented as a 'best practice' example? Mark ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
RE: [Zope3-Users] Re: User preferences for languages- possible?
Hi Giovanni Subject: RE: [Zope3-Users] Re: User preferences for languages- possible? [...] The *must* be a common use case. Why isn't this already solved and documented as a 'best practice' example? It's all done and implemented. Use the z3c.language package, there you'll find a INegotiator implementation, language session and views for switch the language. As Philipp already said, it's simpler to use a session for store user releated infos. The Preference is only needed if you like to store user related data over the time of a session. Regards Roger Ineichen Mark ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: User preferences for languages- possible?
Giovannetti, Mark wrote: The key, as you've correctly identified, is write your own IUserPreferredLanguages adapter (or a variant thereof). I would store the user's preferences in a cookie or a session. This makes things much easier. Simply adapt the request to ISession(request). I'll end up having to do something like this, I suppose. It really sucks, though, because I *want* to use the preferences machinery. Why was it built if it can't be used in certain places - and why aren't the places it can't be used documented? Arrg. Well, it's pretty simple, I've tried to outline it to you: No matter whether you're going the route with sessions or the route with the preferences machinery: Both need to store their information persistently somewhere. That's why they employ local, persistent utilities. Those are only available after certain things have happened: the database has been opened and the publisher has successfully traversed over the sites that contain registered versions of such utilities. Then and only then the getUtility calls work. The ComponentLookupError you were quoting in your original email is, I bet my ass on this, due to the fact that the languages adapter is invoked right when the request is instantiated, at which point none of the steps I outlined above have happened. Note that this might not always work, e.g. when the request is instantiated and the request's locale is first created (because local utilities to store the session data in aren't available at that point). How am I supposed to deal with what you say above? I don't even understand most of it! ;-) I'm sorry if I haven't been clear. I also suggest picking up a copy of my 2nd edition and reading through the chapter on local sites. It explains the concepts of local components. It seems you're hitting that exact problem with the preference stuff as well. The trick here is to stub this out when the adapter is first called, 'stub this out ... ' - I don't understand, sorry. and then later during traversal, when you know the local components are there, you revisit it all again by calling request.setUpLocale() or whatever it is. I don't know what you mean. How is a noob supposed to deal with this? The ++lang++ implementation might give some pointers. The ++lang++ implementation (and ensuing errors when I tested using it) told me that I needed to change BrowserFormLanguages to use IModifiableUserPreferredLanguages. Since I had to do that in order to allow language preferences I decided to get the UserPreferences machinery running for the app. Now I have this problem. I'll try to be a bit clearer now: * Your custom language adapter needs to gracefully deal with an absent preference machinery. In other words, you should catch that ComponentLookupError and fall back to whatever mechanism you want to fallback (I suggest you simply fall back to the super class's implementation). * If the preference stuff is correctly set up, normal views invoking the translation machinery will get your adapter, there will be no ComponentLookupError (because the local site with the persistent utilities is active). * The only problem lies in request.locale which has been initialized too early, when the local site wasn't active and when we caught that ComponentLookupError and simply ignored it. This should be revisited now. I recommend to write an event handler for IBeforeTraverseEvent for ISites that re-initializes request.locale. It would look something like this: from zope.component import adapter from zope.app.component.interfaces import ISite from zope.app.publication.interfaces import IBeforeTraverseEvent @adapter(ISite, IBeforeTraverseEvent) def reinitializeRequestLocale(site, event): event.request.setupLocale() Register that using subscriber handler=.reinitializeRequestLocale /. HTH -- http://worldcookery.com -- Professional Zope documentation and training Next Zope 3 training at Camp5: http://trizpug.org/boot-camp/camp5 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Zope Book: Internationalizing still up to date?
Hi Florian, Read the chapter in Stephan's book. It is excellent and is only out of date on some minor points. Here's one: New: from zope.i18n import MessageFactory _ = MessageFactory(translationdomain) This can be found here: http://kpug.zwiki.org/WhatIsNewInZope33 See section 7 Porting to Zope 3.3.0 Stephan's book ties together a good portion of the details needed for many parts of i18n in zope. Any other good sources about i18n? I found the following helpful: http://wiki.zope.org/zope3/ZPTInternationalizationSupport http://wiki.zope.org/zope3/ZPTInternationalizationExamples I also think that these are useful and up-to-date as far as I can tell: http://wiki.zope.org/ZPT/MetalSpecification11 http://wiki.zope.org/ZPT/TALSpecification14 I've just been learning i18n as well so feel free to post more questions! Answers are even better. ;-) Vinny ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] User preferences for languages- possible?
Hi, [much snippage] Try adding the code snippet shown below. It detects whether a principal is available and only checks for preferences if there is one. class BrowserFormLanguages(BrowserLanguages): implements(IModifiableUserPreferredLanguages) language_store = [] # ignore this for now def __init__(self, request): super(BrowserFormLanguages, self).__init__(request) print created BFL, self.language_store def setPreferredLanguages(self, langs): #prefs = UserPreferences() #print prefs.eods.general.language self.language_store = langs print set language, self.language_store def getPreferredLanguages(self): langs = super(BrowserFormLanguages,self).getPreferredLanguages() if self.language_store: langs = self.language_store + langs form_lang = self.request.get(Language, None) if form_lang is not None: langs.insert(0, form_lang) # LOOK HERE # don't look up preferences unless we have # something which _has_ preferences! if self.request.principal != None: prefs = UserPreferences() print Prefs, repr(prefs) # substitute your own 'None' value case. if prefs.eods.general.language is not None: langs.insert(0, prefs.eods.general.language) print My prefered override, langs return langs The principal annotation error seems to be avoided (since we've made sure we have a principal). The language does seem to be set to the preference for page displays, so what Philipp said about being able to ignore uninteresting things until we've traversed far enough was a good hint. Vinny ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users