WWDC2000 Session 157

Transcript

Kind: captions Language: en so welcome to session 1 57 on necklace ken and localisation I think it's probably about that time on this Thursday afternoon where you're all thinking of going to the beer bash so we'll try to make this short and sweet my name is Kristin I work in the localisation integration group here at Apple in just a couple minutes we're going to bring my cup here one of our engineers and he's going to discuss some of the api's that we developed and how to make your software work well for localization but before we do that I want to say just a couple of words on why we think localisation is actually a very strategic thing it something you should consider it for all of your products so now Apple has always considered localization very strategic and very important to our business and that first line up there on that slide says all you really need to hear about why that is it makes it very obvious approximately one-half of apples apples computers are sold outside the US that's fifty percent of course of the market for your applications as well so now there's no way we can position ourselves in the market this way and so all these matters overseas without significant investment in a high quality localization of our system software in fact this is so important to us that we do we go to great lengths to deliver our operating system software and cpu software it virtually simultaneously with the US product now with necklace 10 we want to do this even better and we put some capabilities in our in our operating system that should make this easier both for us and for you so now the bad news with localization on the Macintosh has always been that the vos was not originally developed as a multilingual system so if you had some resources in the resource Florrick of your application in general they would be you know only in one language and moreover the resources were in the same file is executable they were mixed together with the executable on the same file so that's what it's generally meant was it each different localization of your application would involve multiple independent versions of that application so the result often is that localizing your software means multiple products for you that means multiple products you up to you to ship manufacturer track etc etc now for a large company like Apple that's very feasible for some of you perhaps not so feasible so the good news is that OS 10 now introduces some multilingual to floor directly into the system so it is now possible to fully separate your executables from your resource resources in a chai so you can separate those those two things and this means you can seamlessly consolidate in one package in one executable multiple localizations of a particular application so you can do this very seamlessly as mike is going to describe to you now this just want to highlight this opens up a couple of very exciting possibilities so for example multiple localizations can now be packaged and included in a single product which cuts down significantly on the overhead in delivering alkalis product as well alternatively a language could add on for your app can be easily packaged and delivered at say a web download and this allows you some flexibility and viewing your scheduling around localization and scheduling you know visa VA your us product so these sorts of things or possibilities generated by these leave API so these capabilities in EOS now as you can see we're very excited ourselves to use these these capabilities within our own products and we want to encourage all of you to do that as well in your products so to do that let's get straight to the fun stuff and have them might come up here and give some demonstrations from the end describe these technologies to you so mike is my mic live okay there it is so I want to talk to you just a bit about localization on OS 10 and what we're going to cover is basically what you need to be thinking of to produce an application that's localizable and then how the core foundation frameworks help you in your code to deal with these issues and to build an application which is localizable and then finally we're going to look a little bit about how project builder supports this in the development cycle so okay first of all let's look a little bit about delivering localized application so the old way a separate application for each language right you have to have multiple SK Hughes multiple boxes packaging all this stuff and you also then if you want to have multiple languages supported have to have multiple copies of that app on the system so it's not very good for a multi-user situation where you might have some people using your application with you know who want to run in one language and some other people who want to run it another what we want to move towards is one of the two second possibilities here either you simultaneously ship your application that contains all the localizations together now this would be ideal but we recognize that it's not always totally practical not everybody can spend the effort you know to actually produce all the localizations before they actually can sell one of them so we don't force you to do this but it's totally possible the other option is you just ship localizations as you finish them after you ship the main app but all they are is add-ons it's not a whole nother copy of the application and the installation and merging the new localizations into the app that the user already has now what I want to demo first if we get the demo machine up on the display is just you know what it means for an application to be multiple localized you've probably seen this panel and a few other talks this is the international preferences panel and this list here is basically for me the person who's logged into this machine what's the preferred ordering of languages for me and okay so I might want to be English you know primarily if I launch an application you know we can see that it comes up in English okay easy enough you've probably seen that but what if i reordered this list and say that i'd like to see french first if it's available well now you know it comes up in French when I launch this application these preferences are per users so if you have multiple users who use the machine they all get their own list of ordered languages somebody might want to see Japanese instead the app watch it some Japanese this is the same app recognized right but it's just that depending on what my preferences are it's going to pick the localization that's appropriate all right so that's the end of the first demo here we go back to the slides so all right first of all what does it mean to be localizable localizable is different from localized right localizable means that it's possible to localize this application right the developer can easily produce a localizable application you know they don't have to speak any languages other than their native language they can still produce an application that can be translated and that's what you should be shooting for as a developer you should build an application that could be translated even if you don't plan to do it right now because later you might want to do that and if it's localizable it'll be very easy to do that you won't have to rev your code at all you just have to send your resources off to some translator who will then translate it into the target language send it back to you you put it in the half and it all just works what the developer has to be aware of is not necessarily issues specific to any language or region but just general issues that have to do with localize ability so you want to have your code deal with strings in a way that's flexible enough that it's going to work for springs in any language car stars no good right you want to use something else will get into how that is supported in core foundation you want to look at the same issue with regard to file formats you know don't use a key in your file format if you can help it use something that can represent more languages you want to deal with text input issues so not all languages are as simple and easy to type as English typing Japanese can be very complex because there are so many different characters and you're not going to have a keyboard with 50,000 characters on it so you have to have some sort of input method that lets users type in arbitrarily complex languages you also have to be aware of things like differing formats for dates and numbers and so on and so forth and even potentially differing formats of various hardware standards that are available in different areas of the world and then finally and what people always you know think about sort of first when you think about localization is you have to make sure that all of your interface and all the other resources that might be different for different languages can be all right well let's look at how core foundation actually helps you to achieve this and we won't go through all of the things that I just listed that will cover most of them here some of the main classes i'll call them even though they're not really in core foundation which help you with this sort of thing our CF string a CF character set those help you deal with strings in a way that will not limit you to a particular script see if property list and CF XML parser these are options for file formats that will be totally international I zabal and then see a bundle which is really a very central piece of the system on Mac OS 10 and in addition to all the other things that it does it helps make sure that you're going to get the right versions of your localizable resources when the user runs your application if you use the F bundle properly you won't have to worry about the users preferred language order it will all just work so what about strings CF string should be used as much as you possibly can in your app all right use it instead of karst are everywhere your internal representations avoid converting it to car stars or Pascal strings whenever you can see s strings or Unicode strings so Unicode can represent text in almost any language in the world right maybe any language not all gave almost any language at least and when you do have to actually deal with other character encodings see a string also provides conversion facilities so okay here's what here are a few tips for dealing with strings first of all the unicode spec is fairly complicated and to correctly handle unicode strings there are a lot of details unless this is your domain of expertise you probably don't want to get involved in these details so let's see if string do it okay avoid going through a string character by character in unicode there's almost always an infinite number of ways that basically the same semantic content could be represented in a string there's different you know forms you can use that basically you know don't go through character by character doing comparisons because it's not going to necessarily be the right thing so use built-in character sets to see a character set class allows you to test for membership in certain sets there are a bunch of predefined set so you can say you know is this particular character a letter as the number is that white space punctuation is a diacritic mark there's all kinds of built-in sets if you need to figure out for a particular character or sort of what class this character is in you can use the xterra curse at you can also use the built-in support for collation and comparison so too do you know locale correct sorting or string comparison remember I said that there's various different ways that you could represent the same string in Unicode if you compare them bite for bite two strings that are really the same semantic content might look different if you use the comparison functions in in core foundation they should look to say it and also if you're looking for substrings is it sort of a sub point of the other hole you know comparison and and a collation thing if you're looking for substrings within a bigger string use the api's and core foundations now unfortunately not every API in the world is based on CF string not even every API in Mac OS 10 currently housed es strings API is to deal with it so sometimes you're going to have to convert to some other encoding CF stirring provides the facility to convert back and forth we think are stars or store 255 NCS strings but this is an area where you're going to have to kind of pay attention right not every encoding can support all of the characters in Unicode if you know a few could support all the characters in Unicode you wouldn't need Unicode so if you're going to be converting to some encoding you have to be aware that a particular CF string might have stuff in it that just cannot be converted to a particular encoding in areas where you have to do these conversions just make sure that you're aware of these issues so here's a few selective methods for CF string and CF character set you can create a string from bites of a particular encoding so that's the way that if you were had a car star that you knew within a particular coding or maybe a 30 to 55 or whatever you can create a CF string from that converting the screen whatever encoding it's in into the internal representation now it's not always going to blow the thing up into full Unicode but conceptually you can think of it that way the opposite of that is CF string get bites you can use that to extract a representation of a CF string in a given encoding and this is one because not all coatings can represent all strings that might fail and you have various options too figure that out you can compare strings with CF string compare with options you can find substrings with CF string find with options and then I mentioned character sets a little bit earlier you can get the predefined ones using CF character set get predefined there are a bunch of constants in the header file for that class which basically lists the various predefined sets you can ask for and then once you have a character set you can test whether any individual character is a member of that set with the cs character set is character members ok so file formats again the same sort of issues with strings you don't want to take a file format that's not rich enough to express international context so don't tie yourself to limited screen encodings and okay while I'm mentioning it don't tie yourself to a specific platform this is mostly sort of ending in this issues right so make sure that you take that into account as well use a standard format if it's appropriate so XML is a standard format it's a particularly good choice here because XML is either stored in Unicode or in utf-8 which is a another representation of this just as rich as Unicode and core foundation has support for dealing with XML for simple and small sets of data you can use CF property lists an extremely simple API for serializing and deserialising graphs of sort of data objects like dictionaries and arrays and strings and for more complex stuff you can use the CF XML parser which is a full XML parser that you can use to write xml of whatever format you want so here's a couple of examples the property list stuff is very simple you just hand it a data object and it'll give you back about the the original graph of objects that use to create it in the first place you can then take that graph of objects and hand it to see a property list create xml and it will hand you back a data with the xml in it the parser these are the entry points for the simple entry points for the XML parser there's lots of options there's also a more complex API we're not going to get into that but just so you know core foundation does have support for XML parsing okay this doesn't really relate to core foundation so much but it's another big issue right you need to deal with text input and the way that you deal with text input is actually a little bit different for the carbon and the Coco's back in carbon applications well all the controls are pretty much ready to go so if you're using appearance controls for those things you should be you should be fine for larger text instead of using the older text edit manager consider using the multilingual text edit manager which is unicode based and can deal with these things amount and then also can add more than 32 k of text in it and if you're writing your own text system you can integrate with the text services manager which is basically the sort of lower level input management API for carbon on the cocoa side well the cocoa text system is used for all of the text growing in cocoa and the cocoa text system is fully unicode aware and it also it automatically integrates with the text services manager to do input management and so basically for ninety-nine percent of your cocoa needs just use the tax system if you're writing your own tech system for whatever reason you can implement the text input protocols those automatically integrate with TSM and they allow you to if you're doing your own text entry management take full advantage of the input management facilities okay so here's what we're going to spend a fair amount of time is talking about resources and the bundles resources well okay the term is a little bit overloaded these days resources and we talk about resources on Mac os10 there's kind of two kinds there's bundle resources which you just basically files that live inside of the bundle and there's resource manager resources which are the traditional sort of mac OS 9 resources CF bundle provides a way to deal with both of these things and it also provides the structure for dealing with localization and it knows the proper way to search for resources that may be locale specific inside of a bundle the localized resources are segregated into their own areas we call elkridge folders will actually see some of that in a moment I want to talk a little bit about the difference between regions and languages a region actually includes both a language and a location right so there's the English that we speak here in the United States there's the English that they speak in England there's the French that is spoken in France and there's the French the spoken in Canada we can localize by region so you can actually provide different variants for French Canadian and for branch French or you can just do it by language or you can do it by a combination so let's say that for the most part all your resources are the same whether people are in Canada or in France but there's a small subset that actually have to be specific you can put most of them into language localization areas but put just a small set into the the regional areas and we'll take care of all that for you oh I should mention the region names are actually the iso standard region names so like en underbar you laughs and then so on so forth language names mostly for compatibility reasons our openstep style language names which are typically you know english english versions of language names like English French Japanese so it's German not deutsch even though if you were going to display it in the UI it would be deutsch I'm not going to go through this slide in any great detail you can find this picture in the system overview manual if you want to go through it in detail my point for showing this slide is just to impress upon you that you're better off letting see a bundle finding the resources for you because otherwise these are the places that you have to look and the steps you have to go through to make sure that you're going to get the right version for the users preferences so I don't know if this is readable at all from back there but I mean basically we're going to go out and look in all the appropriate places for these resources and the first place we find it that's one that we're going to use all right I spoke a little bit about the difference between resource management resources and bundle resources just to hit on that again the resource manager resources the ones that are typically found in the resource Fork of an application on Mac OS 9 bundle resources on the other hand or just files that go inside your app wrapper and as I mentioned see a bundle deals with both of these and both of them can be either global or localized so resource manager resources we're trying to get away from relying on the resource fork because we want to be vol format independent and also there's only one resource fork in your applications that we need several places to be able to throw these resources so that you can have multiple localizations so instead we put resource manager resources into the data for it's the same format that used to find in the resource fork it's just in the data port of separate files that go inside the app rapper so the resource manager resources are actually stored in files which are themselves bundle resources of the bundle we separate out the Resource Manager resources that don't need to be localized from the ones that do so you don't have to ship multiple copies of the stuff that doesn't change only multiple copies of the stuff that does change now CF bundle has API to open the resource manager resource Forks and put them onto the chain the resource chain in carbon and it correctly deals with opening both the global and the localized resources to the localized ones that correctly feels with finding the right version for this user's preferences carbon automatically calls this API when your app launches for your application so you don't have to worry about that just like on Mac OS 9 your resource fork was already open for you when your app started but for frameworks or for plugins you can use this bundle API to cause the frameworks or the plugins Resource Manager resources to be added to the carbon resource chain so bundle resources again just files inside the bundle the API on CF bundle basically you ask for resource by name we give you back the Earl of that resource where it resides inside the bundle don't go groping around inside the bundle to try to find them yourselves because again that picture very complex once you've found the Earl that locates this resource inside the bundle you use whatever API is appropriate for the kind of file that you're looking for so you know if it's a tiff file you're going to go off and use a tiff library to open up that image and and parse it if it's a you know an RTF file you're going to go and tell you know some RTF editor to open it or whatever now there's one kind of bundled resource that's handled kind especially by CF bundle and that strings files and I want to kind of spend a little time talking about strings files because for the the carbon folks in the room this is I think one of the first kind of bundle resources that you might want to look at moving some of your resource manager resources to use instead if you're using Resource Manager resources to do thrinng localization I guess there's the fcr number resources and so forth you know okay fine but those are not necessarily the easiest things in the world to maintain and you have to compile them with res and all this other stuff string files provide a nice easy way to do that same thing and so I anticipate that you know carbon developers if they want to get started using some bundle resources instead this might be the first thing that you're going to do any user visible strings obviously should be localizable and strings files are basically key value pairs stored in Unicode in a plain text file well at the plane unicode text file inside your bundle and CF bundle actually have specific API that you can use to locate these strings files open them up cash their contents fetch strings out of them for the particular localization that's appropriate the developer tools also have support for helping you can even generate these strings files just from your code so there's a command-line tool called Jen strings in DP for this is not integrated into the project vulgar bank process but it will be eventually and what is what this tool does is it just sort of goes through all your code looking for places where you're looking up localized strings and then it spits out skeleton strings files that contain all the keys that you're ever going to look for in your code you go in and just fill in the values oh you know what one more thing I want to mention with the strings files CF string has sort of print app like API so you can use format strings and format arguments into them with strings files we actually have support and with GS string itself we have support for argument reordering so if you have two arguments that in English are in you know this order but in you know Japanese they need to be in this order no problem that can all be done all right so here's some of the API for CF bundle for actually locating bundles you can easily get hold of the bundle that contains the application that's running with CF bundle get main bundle if you're a framework or a plug-in and you want to locate the bundle for that framework or that plug-in you can use CF bundle get bundle with identifier you can basically assign a unique identifier to each bundle and then if in that in that bundles code you can look it up by that identifier you can make sure that you get you know the right bundle you don't have to know where it lives on the disk or anything as long as you know your code is running you know that it's loaded it was an app and you'll be able to find that bundle by its identifier the info.plist of a bundle contains a bunch of metadata we're not going to talk too much about that but you can use CF bundle get info dictionary to get the whole info.plist dictionary some of the values in the info dictionary actually end up being localized a lot of the time and they get localized in a separate file called info.plist strings and you can you see a bundle get value for info dictionary key to look up specific values from the info dictionary and that API will actually look into localized stuff first so if you have say a CF bundle name key which is what the finder uses or what carbon uses to display the name of the application in the menu bar you want that to be localized obviously so you can you see a bundle get value for info dictionary key to get that string and make sure that it gets it out of the localized data if it's there otherwise out of the global data you can use CF bundle copy resource Earl to find bundle resources inside the bundle again you just give it the name will go out look for it inside the bundle and return easy appropriate one CS bundle open bundle resource files is the one that you can use in a framework or a plug-in to open up the resource manager resource files inside of the bundle and then CF copy localized string is one of these functions that we have for specifically dealing with these strings files you just give it a key and it will they'll find a string style look that Kiev and return it to you and these localized strings functions are also the thing that that gen strings tool looks for when it's automatically generating strings files for you okay next demo so we get the demo machine back up on the screen I want to show just briefly and I know that this has been shown a couple times before so bear with me if you've seen it what the insides of the bundle looks like we have a little secret shortcut here to actually go inside of a bundle which is usually shown opaque in the finder and let's put that in list mode and give our show some height to play with the only thing that's in the top level of bundle is typically this content directory inside that we have the info.plist which again is this metadata about the bundle and there's been more info on that in other sessions so I'm not going to go into that and the package info which again you may have heard some about but we won't be talking about the actual binary for the application lives inside of a folder named after the platform is supposed to run on you might have another folder in here called Mac OS classic which would contain the binary for mac OS 9 if you had a separate binary format was 9 then what we're really interested in here is the resources directory all the plane files that you see in this directory those are the global resources the ones that don't need to be localized so I don't need to localize the icon file for this application it doesn't have any any text in it and it you know doesn't need to be localized so it sits here one that deserves special mention perhaps is this guy's this is the data fork file that contains the resource manager resources for this application which are global so these are the ones that don't need to be localized now all the local buyers resources go inside these elkridge directories that I talked about a little bit earlier you can see that we have four localizations here 1 for English one for French one for German and one for Japanese the contents of these directories is always identical there should always be identical basically you need a copy of each and every one of these localized resources for each you know language or region that you're localizing for so you know we have the the credits file in French and we have the credit file in English and we have all the various interface builder files we have a standard strings file that you know it's going to be localized this one is the resource manager resources for this application the localized ones so you notice we have a copy in here and we have a copy in here again and use the the bundle ap is the appropriate one is going to get open them on to your resource chain so okay pretty simple and oh the localized plist would also go into the the L proj folders in a file called info.plist strings i believe so that's just another strings file but it has a special name so that we know that it's the one for the plist and it just goes in the L prods with the rest of the localized resources ok that's the end of this demo you can see what the structure of the bundle is you should never have to mess with that project builder knows how to build bundles and we're going to get it to that right now so project folder the new development environment for Mac os10 has full support for building bundles for building multiple localized applications for managing all the details that you need to have taken care of when you're dealing with multiple localized Mac os10 bundles so we know how to build the bundle disk structure you shouldn't involve yourself in that if you can void it at all because well you know we know how to do that and then you shouldn't necessarily have to also know how to do that we let you localize the info.plist data we let you localize your bundle resources we let you localize your resource manager resources all of that so project builder has target types that represent applications frameworks and bundles or loadable plugins all of these basically end up building bundles of one flavor or another each of these targets basically constructs the bundle automatically as it builds and the build system knows where to put all the various pieces then as I think I had mentioned actually project builder has you know full control for managing within your info.plist as well for the resources the target model and project builder is that we have these build phases and so you know we're going to go through and for the target we build each build phase and so there's build phases that will compile your source code there's build phases for frameworks that will copy your headers into the frameworks header directory there's build phases that will copy your bundle resources into the bundle there's a build phase that will run res or res merge on all your are or your darts or C files and put those into the bundle and so this is how project builder deals with building things and the build phases that do bundle resources and resource manager resources know about localization now within the IDE we also help to enforce some of the requirements for CF bundles one of those requirements is that a resource has to be either global or localizable okay you shouldn't have a file in your L proj directory and also have it at the top level of the resources if you do the global one is the only one that will be found that seems a little backwards the reason that's done is for performance you're not supposed to have them both if you do have them both first we look for as the global one because we only have to look in one place for that we also make sure that whatever the development language of your project is you'd have to have a full set of resources for those you should have a full set of resources for any other regions that you support but if you don't for a particular resource will fall back on the development region version and that's why you have to have a development regent version that means that we'll always be able to find at least one version of this resource and then for the platform specific stuff we require that there be a generic one if you have any platform specific ones and that's just in case say another platform was to be supported at a later date if you only had platform specific ones which ones we use right you didn't anticipate the new platform if there's a generic one in there though we can use that so all right let's actually look at how this gets done in project builders now what I have is a slightly modified version of the simple text project that ships as an example on ls10 and when I say slightly modified what I've done is I've made simple text localizable ready okay so simple text wasn't quite fully set up to be localizable but I've tweaked it around a little so it is we can see all there are files that are in the project and these so these are the things that are going to go you know through res and build the resource manager resources that simple text needs now first let's go ahead and build this while that's building maybe I'll point out that I've also sort of broken up the dot our files a little further than they are in the in the default simple text I've actually taken out and put in a separate file all of the stuff that doesn't need to be localize right okay heck strings don't need any localization so we put all this stuff into the global one and this is the one that will leave a loan all the rest of the files contain stuff that does need to be localized and and we'll we'll see how those get localized in a minute looks like we're to the link step here I'm going to actually pull open the the sort of more verbose build log here you can see that we we ran Reds here on a bunch of resource files and all of them are being read into the simple text rsrc which sits directly in the resources directory of the bundle right so these are all global resources at this point the all the our files were merged together and put into one dot are SRC file in the data park all right let's prove that this actually works alright so here's simple text I can bring up from the fine panel and so on and so forth okay fine simple text has a bug yes now okay so i have this application now that's localizable but it's not localized right how do I localize it well these are the files again that needs to be localized this one the global stuff filed this one does not need to be localized but this one these these all do so what I'm going to do is I'm going to go to the project inspector the inspector can act on multiple selection so you do all the stuff in a batch and there's this localization of platforms pull down menu and all you really have to do here is say okay I'd like all these to be localized please you'll notice that they all got disclosure triangles and what that shows if you disclose it it shows a list of all of the different variants that we have for this localized resource and so when we first make it localized we just get English which is the development region for this project and that's what we start out with but the whole point here is we want to actually localize it so once we've made these localizable resources we can go ahead and add an invariant so let's say add one for French you'll notice that for the ones i disclose that of the french version here initially when you add a new region variant it starts out as a copy of the development region so if i open up the this file which actually seems to contain a lot of the strings will see that the French version is in English right because it just copied the English file okay now i'm not going to make you sit here watch me my poor command of french here so i actually had a colleague localized this this one for me and i have this little cheater file and we'll go ahead and just copy the contents out of there and go back to the french version of localized are and we'll just replace it save that so now we have this version which I go up the part that actually was localized you can see you know it has been localized in French okay let's build that now it didn't build any of the codes we already built that now if you notice though now it's running res on some of these files and it's putting them into the localized rsrc of the English elkridge if doing some more of them for the French doll proj right as we have French versions for everything now and then finally it's doing the global one for the the one that we didn't localize okay and now we can run hopefully it'll still come up in English because I haven't changed my language preference ooh you know what though I forgot to change my preference back to english after the first demo so ra well here it is in French all right let's do this in the right order though all right so you run this and it'll come up in English actually you'll notice that before I had left the preference ordered Japanese French English right we hadn't localized it into Japanese but we have localized it in the French so it showed up in French even though I would have preferred Japanese if there had been one okay so here it is in English right we still have the fine panel it's an a okay fine but if we go back here and we say okay well let's make that French instead and run it again okay here comes in French and you'll see that in this case just doing the strings isn't given quite be enough we'll probably have to go in and tweak some as a titl resources to change them the control sizes only get when I make this actually fully localized to the French but you get the idea right so that's as easy you know as it is to actually support this stuff in project builder and that is the end of that demo so that pretty much concludes the content here all of my pointers point backwards all of these sessions have already taken place if you saw them good for you if you didn't well okay maybe some of these slides or even the video for these presentations will be available at some point and if they are you might take a peek at some of them at core foundation is a wonderful technology for dealing with these localization issues as well as a lot of other stuff so definitely check out the core foundation stuff if you want to learn about project builder there's the project builder sessions there's the application packaging and document typing talk that are another gave earlier this afternoon that deals with other bundle issues there's the Apple localization tools talk which was in this room right before this talk and then the one that isn't already over there's the text and international feedback session tomorrow morning so tim holmes is the one to contact about this technology vmail dresses there and now i'll invite a few people to come up hopefully they showed up or QA you