| 332 | |
| 333 | |
| 334 | class GNUTranslations(NullTranslations): |
| 335 | # Magic number of .mo files |
| 336 | LE_MAGIC = 0x950412de |
| 337 | BE_MAGIC = 0xde120495 |
| 338 | |
| 339 | # The encoding of a msgctxt and a msgid in a .mo file is |
| 340 | # msgctxt + "\x04" + msgid (gettext version >= 0.15) |
| 341 | CONTEXT = "%s\x04%s" |
| 342 | |
| 343 | # Acceptable .mo versions |
| 344 | VERSIONS = (0, 1) |
| 345 | |
| 346 | def _get_versions(self, version): |
| 347 | """Returns a tuple of major version, minor version""" |
| 348 | return (version >> 16, version & 0xffff) |
| 349 | |
| 350 | def _parse(self, fp): |
| 351 | """Override this method to support alternative .mo formats.""" |
| 352 | # Delay struct import for speeding up gettext import when .mo files |
| 353 | # are not used. |
| 354 | from struct import unpack |
| 355 | filename = getattr(fp, 'name', '') |
| 356 | # Parse the .mo file header, which consists of 5 little endian 32 |
| 357 | # bit words. |
| 358 | self._catalog = catalog = {} |
| 359 | self.plural = lambda n: int(n != 1) # germanic plural by default |
| 360 | buf = fp.read() |
| 361 | buflen = len(buf) |
| 362 | # Are we big endian or little endian? |
| 363 | magic = unpack('<I', buf[:4])[0] |
| 364 | if magic == self.LE_MAGIC: |
| 365 | version, msgcount, masteridx, transidx = unpack('<4I', buf[4:20]) |
| 366 | ii = '<II' |
| 367 | elif magic == self.BE_MAGIC: |
| 368 | version, msgcount, masteridx, transidx = unpack('>4I', buf[4:20]) |
| 369 | ii = '>II' |
| 370 | else: |
| 371 | raise OSError(0, 'Bad magic number', filename) |
| 372 | |
| 373 | major_version, minor_version = self._get_versions(version) |
| 374 | |
| 375 | if major_version not in self.VERSIONS: |
| 376 | raise OSError(0, 'Bad version number ' + str(major_version), filename) |
| 377 | |
| 378 | # Now put all messages from the .mo file buffer into the catalog |
| 379 | # dictionary. |
| 380 | for i in range(0, msgcount): |
| 381 | mlen, moff = unpack(ii, buf[masteridx:masteridx+8]) |
| 382 | mend = moff + mlen |
| 383 | tlen, toff = unpack(ii, buf[transidx:transidx+8]) |
| 384 | tend = toff + tlen |
| 385 | if mend < buflen and tend < buflen: |
| 386 | msg = buf[moff:mend] |
| 387 | tmsg = buf[toff:tend] |
| 388 | else: |
| 389 | raise OSError(0, 'File is corrupt', filename) |
| 390 | # See if we're looking at GNU .mo conventions for metadata |
| 391 | if mlen == 0: |
no outgoing calls
searching dependent graphs…