Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2009-01

Bug in Gettext?

9 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Klaus Reimer

Hello,

I have a question regarding the Unit "gettext" which is used to parse a MO file and to translate texts with this file.

I have writte a Lazarus application which uses the DefaultTranslator class to translate the application. This translator uses the gettext Unit of Free Pascal. The problem is that all strings which uses a "message context" in the PO file are not
automatically writes message contexts to the PO file when same texts are used in different parts of the application.

So my first thought was that this is a bug in the DefaultTranslator that it does not pass the message context to the gettext unit. I was going to add this to the DefaultTranslator unit but then I noticed that i have no idea how to translate a text whcih uses a message context with the gettext unit.

So can someone tell me how to do this? According to the GNU gettext documentation the context is prefixed to the original text separated with an EOT character (#4). So the "orig" text in my case is this:

'TFORM1.BUTTON1.CAPTION' + #4 + 'Test'

But If I pass this string to the translate method of gettext then this also returns an empty string because the generated hash code for this string is not found in the hash table of the MO file.

So how can I translate texts which uses message contexts?

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Michael Van Canneyt
to Klaus Reimer
Klaus Reimer wrote 29 lines
Hello, I have a question regarding the Unit "gettext" which is used to parse a MO file and to translate texts with this file. I have writte a Lazarus application which uses the DefaultTranslator class to translate the application. This translator uses the gettext Unit of Free Pascal. The problem is that all strings which uses a "message context" in the PO file are not automatically writes message contexts to the PO file when same texts are used in different parts of the application. So my first thought was that this is a bug in the DefaultTranslator that it does not pass the message context to the gettext unit. I was going to add this to the DefaultTranslator unit but then I noticed that i have no idea how to translate a text whcih uses a message context with the gettext unit. So can someone tell me how to do this? According to the GNU gettext documentation the context is prefixed to the original text separated with an EOT character (#4). So the "orig" text in my case is this: 'TFORM1.BUTTON1.CAPTION' + #4 + 'Test' But If I pass this string to the translate method of gettext then this also returns an empty string because the generated hash code for this string is not found in the hash table of the MO file. So how can I translate texts which uses message contexts?

Probably the error is in the hash code ?
Does GNU gettext take the #4 into account when it generates the hash code ?

Michael.

Reply by email

Klaus Reimer
to Michael Van Canneyt
Michael Van Canneyt wrote
Probably the error is in the hash code ? Does GNU gettext take the #4 into account when it generates the hash code ?

gettext doesn't has its own hash method. It uses the global hash function defined in the objpas unit. I already wondered how this can its the same algorithm as used by the msgfmt tool of gettext. Don't know. I have no experience with hash algorithms. But this code generates different hash codes so maybe this proves that #4 is not ignored in the hash:

  WriteLn(Hash('hallo' + #4));
  WriteLn(Hash('hallo' + #3));

Output:

115880692
115880691

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Michael Van Canneyt
to Klaus Reimer
Klaus Reimer wrote 13 lines
Michael Van Canneyt wrote: > Probably the error is in the hash code ? > Does GNU gettext take the #4 into account when it generates the hash code ? gettext doesn't has its own hash method. It uses the global hash function defined in the objpas unit. I already wondered how this can its the same algorithm as used by the msgfmt tool of gettext. Don't know. I have no experience with hash algorithms. But this code generates different hash codes so maybe this proves that #4 is not ignored in the hash: WriteLn(Hash('hallo' + #4)); WriteLn(Hash('hallo' + #3));

Yes,

I meant: but based on what does GNU gettext calculates the hash code ? Is it on:
String
Context+String
Context+#4+String ?

Michael.

Show quoted text 13 lines
Output: 115880692 115880691 -- Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Klaus Reimer
to Michael Van Canneyt
Michael Van Canneyt wrote 5 lines
I meant: but based on what does GNU gettext calculates the hash code ? Is it on: String Context+String Context+#4+String ?

That's exactly my problem. Lazarus only passes "String" to gettext and this fails (And the reason is clear). My plan was to change this so if gettext says "I don't have anything for 'String'" then the DefaultTranslator asks again but this time also passes the context. But Context+String and Context+#4+String also does not work so I have no idea how I can modify DefaultTranslator so it gets the correct answer from the gettext unit.

My current theory is that the hash algorithms of Free Pascal and msgfmt are nearly the same but not exactly the same so a simple character like #4 kills the compatibility.

The GNU gettext documentation only says this: "The hash table contains indices to the sorted array of strings in the MO file. Conflict resolution is done by double hashing. The precise hashing algorithm used is fairly dependent on GNU gettext code, and is not documented here."

This sounds like the algorithm isn't "specified" and therefor may change in future versions. So maybe it's better if the gettext unit created its own hash table when the MO file is parsed?

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Michael Van Canneyt
to Klaus Reimer
Klaus Reimer wrote 27 lines
Michael Van Canneyt wrote: > I meant: but based on what does GNU gettext calculates the hash code ? > Is it on: > String > Context+String > Context+#4+String ? That's exactly my problem. Lazarus only passes "String" to gettext and this fails (And the reason is clear). My plan was to change this so if gettext says "I don't have anything for 'String'" then the DefaultTranslator asks again but this time also passes the context. But Context+String and Context+#4+String also does not work so I have no idea how I can modify DefaultTranslator so it gets the correct answer from the gettext unit. My current theory is that the hash algorithms of Free Pascal and msgfmt are nearly the same but not exactly the same so a simple character like #4 kills the compatibility. The GNU gettext documentation only says this: "The hash table contains indices to the sorted array of strings in the MO file. Conflict resolution is done by double hashing. The precise hashing algorithm used is fairly dependent on GNU gettext code, and is not documented here." This sounds like the algorithm isn't "specified" and therefor may change in future versions. So maybe it's better if the gettext unit created its own hash table when the MO file is parsed?

Currently it reads the hash table from the .mo file. The reason it is stored there is speed. I think it would be unwise to recalculate the hash value.

I don't think GNU gettext will change it's hash algorithm: it would mean that newer programs can no longer read old .MO files (or vice versa) so I think it is better to find out why the hash values are different.

A simple routine calculating the hash value of all ascii values both in C and Pascal should do it, no ?

Michael.

Reply by email

Klaus Reimer
to Michael Van Canneyt
Michael Van Canneyt wrote
A simple routine calculating the hash value of all ascii values both in C and Pascal should do it, no ?

Unfortunately I was not yet able to locate the responsible code in the GNU gettext source... Maybe I try again later if I find the time.

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Klaus Reimer
to Klaus Reimer
Klaus Reimer wrote
Unfortunately I was not yet able to locate the responsible code in the GNU gettext source... Maybe I try again later if I find the time.

Now I found the hash function in GNU gettext. The algorithm is the same as in Free Pascal and the result for a string like 'TABOUTFORM.CAPTION'#4'About' is also the same. So that's not the problem... I think I have to dive deeper into the msgfmt tool. The documentation mentions "double hashing" which is used when messages collide (which is the case here because I have multiple "About" texts in the application).

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email

Klaus Reimer
to Klaus Reimer

Hello,

well that's strange but I think it was simply my error and may be it was a simple typo... gettext unit is working correctly. Passing 'TFORM1.BUTTON1.CAPTION'#4'Test' to it works correctly now.

So Free Pascal works fine, it's just the DefaultTranslator which is not using the message context. I was able to fix this so I'm going to open a bug report with a patch.

Thanks for listening.

Bye, K <http://www.ailis.de/~k/> [A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391] (Finger to get public key)

Reply by email