From: Steve K. <s.k...@bu...> - 2004-11-19 12:09:28
|
A thought occurs to me on this ... It is true that table-based translations are easier to maintain. It is also true that this can increase database activity to lookup the text. However, what if we have table-based translations and load these into a session variable at logon ? Something like this ... Table 'Languageen' for English, Table 'Languageit' for Italian, Table 'Languagefr' for French, etc. Just create a new table for a new language. Structure ID integer not null text text 'en' is the default, 'fr' is the user's preferred language (for example) At user logon, load the ID, default text and translation text into a session array. It then a simple matter to parse the session array for the string you need using either the ID or the default text as the key. This also means you could use the ID or the default text in the code, which would maintain readability. Plus, you could get real fancy with the placement of variables within the text should the need arise. The ID option would also allow for different translations of the same string for different contexts (which can be a real problem - believe me, I've been there ...). The obvious downside here is increased memory usage - I guess about 1Mb per user session. Also, if you want output in a different language (say for a report), then you still need to do a lookup for the text. There would be a delay at logon (and if the user changes their language prefs) while the array is loaded, but I don't think that is a problem. With this type of mechanism, language maintenance becomes pretty trivial. New text and new languages could be easily added. The work done so far should not be compromised by this approach since rewriting the _() function should be sufficient for 90% of it. Opinions, comments ? (Feel free to tell me I'm talking rubbish :-)) Kitch On Fri, 2004-11-19 at 11:18 +0100, Steve Kitchen wrote: > Interesting points. >=20 > I have seen various implementations along these lines - > phpgroupware/eGroupware use table based translations and have a lang > function that does the lookup. There is also a string parser to insert > data variables at the appropriate points in the string. This does have > the advantage of dealing very nicely with variations in grammatical > constructs. >=20 > The trade-off is in database access - it is guaranteed that every page > load will have to access the db tables for its textual content. >=20 > With a system like web-ERP the db engine will be hyperactive anyway > and disk access is the most probable bottleneck. If we store screen > text in the db as well, this will adversely affect the performance. >=20 > Of course, if fiber-channel RAID arrays were cheap, this would be the > way to go ... :-) >=20 >=20 > Kitch >=20 >=20 > On Thu, 2004-11-18 at 23:02 +0100, Stins, Dick www.Zion-IT.com wrote: >=20 > > I know it is late, but better late then never. You're example > > refreshed my memory. > > =20 > > In several development standards and projects, I was used to have an > > error/warning/information message coding system. > > =20 > > Every message should have it's own unique code/number followed with > > the text. I could happen that at different places in the code > > appears the same message like: "Wrong Code Entered". > > =20 > > In the system it would be coded with a function like: > > display_message(=20 > > 'E' , //E=3Dmessage type Error > > 'A', //A=3Dabort script or I=3Dinformational or > > W=3Dwarning > > 'WE001' ); // Wrong code Entered > > =20 > > At another error situation: > > display_message(=20 > > 'E' , //E=3Dmessage type Error, I=3DInformationa= l, > > W=3Dwarning, ... > > 'A', //A=3Dabort script or C=3DContinue or ... > > 'WE002' ); // Wrong code Entered WE=3DWeb Erp 002=3Dthe mess= age > > number > > =20 > > The function will fetch the message based at the unique code (like > > 'WE002' ) and does what it should do.=20 > > =20 > > Both messages are the same, but the only difference is the exact > > place in a script where it is raised from. > > =20 > > When you find the exact message for more then one unique code, then > > there are a few reasons why this happens: > > - the message is not detailed enough > > - it is coded inefficient, because the same code is repeated at > > several places, while a function/procedure is able to prevent this > > and ...... so it helps to increase the quality of the program. > > - it increases performance (but I have never seen a good example of > > this) > > =20 > > Where do you store the messages? Normally in a table, so it would be > > easy to update the messages without changing the source. An extra > > column could be entered to implement multilanguage for messages like > > these. May be are their other good implementation methods. > > =20 > > When you display also the unique code, then you will always be able > > very easily to find the exact line in a script where the error is > > raised from. That's very handy for debugging and answering questions > > of end-users. > > =20 > > Sometimes, you need to be able to show parameters in a message like: > > "You entered the wrong code: #1 in #2" > > =20 > > For this we need a function/procedure which allows 2 parameters. > > display_message(=20 > > 'E' , //E=3Dmessage type Error, I=3DInformationa= l, > > W=3Dwarning, ... > > 'A', //A=3Dabort script or C=3DContinue or ... > > 'WE003', // You entered the wrong code: #1 in #2 WE=3DWeb > > Erp 002=3Dthe message number > > $code, > > 'index.php' ); > > =20 > > Resume advantages: > > - A standardised message system is good for the coding quality > > - It is much easier to find the exact script + line where the > > message is comming from > > - We would be able to update the message without the chance you make > > some typo in the script, because there is no need for updating a > > script when we need to update a message. > > - improves quality, since it shows generic messages are not > > detailed enough > > - lot's of messages which are equal, tells us that there might be > > some code lines be coded twice or more or the message is not > > detailed enough. > > - ..... > > =20 > > My suggestions is to do the following steps: > > - do we like this? All or only parts of it or nothing? > > - how do we want to implement this? Create a message class? And a > > table? Or use the translation package? Or ... > > - there is no need to rewrite all scripts. I would be good enough > > when we use a message system like this for all coding which is new > > or rewritten for new functions. > > =20 > > With best regards, > > =20 > > Dick Stins > > ---- Original Message -----=20 > >=20 > > From: Daintrees=20 > > To: web...@li...=20 > > Sent: Thursday, November 18, 2004 8:48 PM > > Subject: Re: [Web-erp-developers] po tidy up > > =20 > > =20 > > I tried to remove punctuation - only at the end of sentences > > and broke up strings around html. > > Notice you did SelectOrderItems.php too - a misson in itself > > - both you and Steve did this one! > > =20 > > This tidy up is a misson Kitch - good job you seem to have > > broad shoulders - and chose to accept it :-) > > =20 > > Phil > > =20 > > ----- Original Message -----=20 > > From: Steve Kitchen=20 > > To: web...@li...=20 > > Sent: Friday, November 19, 2004 8:17 AM > > Subject: Re: [Web-erp-developers] po tidy up > > =20 > > =20 > > For me, the second option is better. Consider > > something like > > =20 > > '<BR>ERROR ! The code could not be found. Please > > re-enter the GL reference' > > =20 > > and > > =20 > > '<BR>ERROR ! The code could not be found. Please > > re-enter the customer code' > > =20 > > =20 > > 'ERROR' and 'The code could not be found' are common > > phrases that are scattered throughout the > > application. When split up as suggested, only one > > instance of the text 'ERROR' and the text 'The code > > could not be found' are needed in the .po file. > > =20 > > Also, the current .po file is approaching 400K in > > size, so any consolidation to reduce this should be > > considered A Good Thing (tm) :-) > > =20 > > =20 > > Kitch > > =20 > > =20 > > =20 > > On Thu, 2004-11-18 at 14:03 -0500, Steve Kaill > > wrote: > > =20 > > > =EF=BB=BF=20 > > > Although I stuck to the majority of these > > > recommendations I would have one question. What > > > about punctuation within a string. e.g. > > > =20 > > > '<BR> The code could not be found. Please verify > > > and re-enter.' > > > =20 > > > What about that period and space in the middle? > > > Should it be > > > =20 > > > '<BR> ' . _('The code could not be found. Please > > > verify and re-enter') . '.' > > > =20 > > > or > > > =20 > > > '<BR> ' . _('The code could not be found') . > > > '. ' . _('Please verify and re-enter') . '.' > > > =20 > > > Steve > > >=20 > > > ----- Original Message -----=20 > > > From: Steve Kitchen=20 > > > To: > > > web...@li...=20 > > > Sent: Thursday, November 18, 2004 1:48 PM > > > Subject: Re: [Web-erp-developers] po tidy > > > up > > > =20 > > > =20 > > > OK, I've had a look at all this stuff and > > > here's the low-down .... > > > =20 > > > =20 > > > As Phil says, things are somewhat messy > > > with duplicate definitions, bits of > > > puctuation, bits of HTML and the like in > > > the text strings. > > > =20 > > > I will go through all the existing modules > > > and bash it into a more consistent form (I > > > must be mad ...). > > > =20 > > > =20 > > > Can I request that when you put _() > > > strings in your code you=20 > > > =20 > > > do not put spaces at the start or end > > > of the string > > > do not put HTML tags in the string - > > > break it up into pieces > > > do not put punctuation in the string - > > > again, break it up into pieces > > > be consistent about case > > > =20 > > > =20 > > > I've made a web page to help with > > > translating (default on the left, your > > > translation on the right) which I will > > > send in when it looks a bit prettier :-) > > > =20 > > > =20 > > > Catch y'all later ... > > > =20 > > > Kitch > > > =20 > > > On Fri, 2004-11-19 at 11:00 +1300, Phil > > > Daintree wrote: =20 > > > =20 > > > > OK Kitch I got a lot of this in now - nee= d to go back and do some double=20 > > > > checking though - Jesse just sent Special= Order.php which missed the cut - its=20 > > > > bed time here - can here knocking on the = wall telling me to knock off!! > > > >=20 > > > > Checking in CreditStatus.php; > > > > Checking in CustomerAllocations.php; > > > > Checking in CustomerBranches.php; > > > > Checking in DeliveryDetails.php; > > > > Checking in DiscountCategories.php; > > > > Checking in DiscountMatrix.php; > > > > Checking in Logout.php; > > > > Checking in SelectOrderItems.php; > > > > Checking in ShipmentCosting.php; > > > > Checking in Shipments.php; > > > > Checking in Shippers.php; > > > > Checking in Shipt_Select.php; > > > > Checking in ShiptsList.php; > > > > Checking in StockStatus.php; > > > > Checking in SuppCreditGRNs.php; > > > > Checking in SuppInvGLAnalysis.php; > > > > Checking in SuppPaymentRun.php; > > > > Checking in SuppShiptChgs.php; > > > > Checking in SuppTransGLAnalysis.php; > > > > Checking in SupplierAllocations.php; > > > > Checking in SupplierContacts.php; > > > > Checking in SupplierCredit.php; > > > > Checking in SupplierInquiry.php; > > > > Checking in SupplierInvoice.php; > > > > Checking in Suppliers.php; > > > >=20 > > > > quite a flourish to finish on..... > > > >=20 > > > > and of course=20 > > > > Checking in locale/en/LC_MESSAGES/message= s.po; > > > >=20 > > > >=20 > > > > Worried about introducing bugs with such = a lot at break neck speed. > > > > I re-ran xgettext to update messages.po > > > >=20 > > > >=20 > > > > An Italian chap contacted me spelling out= duplications in the .po as it was=20 > > > > which may be useful: > > > >=20 > > > > > > I started translating web erp in ital= ian, but realized that messages.po > > > > > > in italian is not complete > > > > > > > > > > > > even *.po in english seem not perfect= either: > > > > > > > > > > > > -------------------------------------= ------------------------------- > > > > > > bash-2.05b$ msgfmt *.po > > > > > > msgfmt: index.po: warning: Charset "C= HARSET" is not a portable encoding > > > > > > name. > > > > > > Message co= nversion to user's charset might > > > > > > not work. > > > > > > msgfmt: messages.po: warning: Charset= "CHARSET" is not a portable > > > > > > encoding name. > > > > > > Message= conversion to user's charset might > > > > > > not work. > > > > > > messages.po:7: duplicate message defi= nition > > > > > > index.po:8: ...this is the location o= f the first definition > > > > > > messages.po:20: duplicate message def= inition > > > > > > index.po:418: ...this is the location= of the first definition > > > > > > messages.po:844: duplicate message de= finition > > > > > > index.po:414: ...this is the location= of the first definition > > > > > > messages.po:1165: duplicate message d= efinition > > > > > > index.po:293: ...this is the location= of the first definition > > > > > > messages.po:1800: duplicate message d= efinition > > > > > > index.po:29: ...this is the location = of the first definition > > > > > > messages.po:3793: duplicate message d= efinition > > > > > > index.po:410: ...this is the location= of the first definition > > > > > > messages.po:3849: duplicate message d= efinition > > > > > > index.po:378: ...this is the location= of the first definition > > > > > > messages.po:4087: duplicate message d= efinition > > > > > > index.po:390: ...this is the location= of the first definition > > > > > > messages.po:4410: duplicate message d= efinition > > > > > > index.po:209: ...this is the location= of the first definition > > > > > > messages.po:5518: duplicate message d= efinition > > > > > > index.po:149: ...this is the location= of the first definition > > > > > > messages.po:6958: duplicate message d= efinition > > > > > > index.po:189: ...this is the location= of the first definition > > > > > > messages.po:7683: duplicate message d= efinition > > > > > > index.po:153: ...this is the location= of the first definition > > > > > > messages.po:9314: duplicate message d= efinition > > > > > > index.po:21: ...this is the location = of the first definition > > > > > > messages.po:9326: duplicate message d= efinition > > > > > > index.po:257: ...this is the location= of the first definition > > > > > > messages.po:9368: duplicate message d= efinition > > > > > > index.po:265: ...this is the location= of the first definition > > > > > > messages.po:9641: duplicate message d= efinition > > > > > > index.po:25: ...this is the location = of the first definition > > > > > > messages.po:9649: duplicate message d= efinition > > > > > > index.po:33: ...this is the location = of the first definition > > > > > > messages.po:9653: duplicate message d= efinition > > > > > > index.po:37: ...this is the location = of the first definition > > > > > > messages.po:9657: duplicate message d= efinition > > > > > > index.po:41: ...this is the location = of the first definition > > > > > > messages.po:9661: duplicate message d= efinition > > > > > > msgfmt: too many errors, aborting > > > > > > -------------------------------------= -------------------------- > > > > > > > > > > > > if you can provide a valid/updated me= ssages.po I will happily translate > > > > > > it in italian > > > > > > > > > > > > bye > > > > > > > > > > > > xlyz > > > >=20 > > > >=20 > > > > A few minor points men - I'm trying to us= e Jesse's prnMsg function wherever=20 > > > > possible - this does mean there is one co= mmon way for displaying messages and=20 > > > > we can muck about with the formats as we = like - it is pretty rudimentary but=20 > > > > I like the idea of some kind of standardi= sation of messages. Many echo=20 > > > > statements can lose the <BR> and slot int= o a prnMsg instead. > > > >=20 > > > > I am probably slightly autistic in my zea= l for having the code nicely indented=20 > > > > too - I tend to break after </TD> so the = next line starts on a <TD> > > > > HTML in CAPS ideally. SQL broken up field= by field line breaks before FROM.=20 > > > > WHERE, AND, GROUP BY, ORDER BY > > > >=20 > > > > All very picky stuff - dont bother if you= dont want to I happy to have the=20 > > > > code anyway you like - but I try to modif= y it to comply with that=20 > > > > Contributing.txt doc before committing to= CVS. > > > >=20 > > > > WE DID IT! > > > >=20 |