Override this method to support alternative .mo formats.
(self, fp)
| 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: |
| 392 | # Catalog description |
| 393 | lastk = None |
| 394 | for b_item in tmsg.split(b'\n'): |
| 395 | item = b_item.decode().strip() |
| 396 | if not item: |
| 397 | continue |
| 398 | # Skip over comment lines: |
| 399 | if item.startswith('#-#-#-#-#') and item.endswith('#-#-#-#-#'): |
| 400 | continue |
| 401 | k = v = None |
| 402 | if ':' in item: |
| 403 | k, v = item.split(':', 1) |
| 404 | k = k.strip().lower() |
| 405 | v = v.strip() |
| 406 | self._info[k] = v |
| 407 | lastk = k |