Jump to content

[Python] GetText


Recommended Posts

Antes que comecem a dizer que scripts que façam isto não faltam, eu fiz isto antes de ir ver se existia, só depois é que reparei que a biblioteca padrão até já tem...

Este script permite traduzir strings dos ficheiros mo, nos dois sentidos, faz cache (dois tipos) e permite exportar.

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""Coded by Fabio André Domingues (fnds)
___________________________________________________________________________

python GetText - It can read MO files and use them for translating strings.


Classes:
   GetText(mo_file, cache_type=NONE).

Constants:
   ERROR = 'GetTextError';
   NONE = None;
   ALL = 1;
   ALL_PROGRESSIVE = 2;
   INDEXS = 3;
   VALUES = 4."""

from sys import exit as _sys_exit
from struct import unpack as _unpack

ERROR = 'GetTextError'
NONE = None
ALL = 1
ALL_PROGRESSIVE = 2
INDEXS = 3
VALUES = 4

class GetText():
   """    __init__(mo_file, cache_type=NONE):
           mo_file - path to mo file;
           cache_type - type of cache mechanism:
               NONE - no cache;
               ALL - all strings are cached, mo file is closed;
               ALL_PROGRESSIVE - strings are cached when used.

       get_value(index_string) - return de value of index_string.

       get_index(value_string) - return de index os value_string.

       export(what):
           what:
               ALL - return a dict {index: value} with all strings;
               INDEXS - return a tuple (index1, index2) with all indexs;
               VALUES - return a tuple (value1, value2) with all values;"""

   def __init__(self, mo_file, cache_type=None):
       self._file = open(mo_file, 'rb')
       self._byte_order = ''
       self._cache_type = cache_type

       #Check file and define byte order
       # < - little-endian
       # > - big-endian
       magic = self._read_int()
       if magic == 2500072158:
           self._byte_order = '<'
       elif magic == 3725722773:
           self._byte_order = '>'
       else:
           raise ERROR, '"%s" is not MO file.' % file

       #File info
       revision = self._read_int()
       self.total = self._read_int()
       indexs_pos = self._read_int()
       values_pos = self._read_int()

       #Get table of indexs
       self._file.seek(indexs_pos)
       self._table_indexs = self._read_int_tuple(self.total*2)

       #Get table of values
       self._file.seek(values_pos)
       self._table_values = self._read_int_tuple(self.total*2)

       #Check cache_type
       if self._cache_type == NONE:
           self._cache_contents = None
       elif self._cache_type == ALL:
           self._cache_contents = self._extract_all()
           self._file.close()#Cache all -> close file
       elif self._cache_type == ALL_PROGRESSIVE:
           self._cache_contents = {}
       else:
           raise ERROR, 'Incorrect value of cache_type. [NONE, ALL, ALL_PROGRESSIVE]'

   #### Nucleo Duro ####
   #Read data from mo_file 
   def _file_read(self, bytes):
       data = ''
       while bytes > 0:
           chunk = self._file.read(bytes)
           data += chunk
           bytes -= len(chunk)       
       return data

   #Unpack one structure, return string
   def _read_int(self):
       return _unpack(self._byte_order+'L', self._file_read(4))[0]

   #Unpack many structure, return tuple
   def _read_int_tuple(self, count):
       return _unpack(self._byte_order+'L'*count, self._file_read(4*count))

   #Extract all indexs/values from file, return dict {index: value}
   def _extract_all(self):
       all = {}
       for i in range(self.total):
           self._file.seek(self._table_indexs[i*2+1])
           index = self._file_read(self._table_indexs[i*2])
           self._file.seek(self._table_values[i*2+1])
           all[index] = self._file_read(self._table_values[i*2])
       return all

   #Extract all indexs from file, return tuple (index1, index2)
   def _extract_indexs(self):
       indexs = ()
       for i in range(self.total):
           self._file.seek(self._table_indexs[i*2+1])
           indexs += self._file_read(self._table_indexs[i*2]),
       return indexs

   #Extract all values from file, return tuple (value1, value2)
   def _extract_values(self):
       values = ()
       for i in range(self.total):
           self._file.seek(self._table_values[i*2+1])
           values += self._file_read(self._table_values[i*2]),
       return values
   #### fim Nucleo Duro ####

   #Return de value of index
   def get_value(self, index_string):
       if self._cache_type == ALL:#Cache all, get cache item
           if index_string in self._cache_contents:
               return self._cache_contents[index_string]
           else:
               raise ERROR, 'Index "%s" don\'t have value.' % index_string
       elif self._cache_type == ALL_PROGRESSIVE:#Cache progressive
           if index_string in self._cache_contents:#If item in cache get it
               return self._cache_contents[index_string]
           else:#else get from file and put in cache
               for i in range(self.total):
                   self._file.seek(self._table_indexs[i*2+1])
                   index = self._file_read(self._table_indexs[i*2])
                   if index_string == index:
                       self._file.seek(self._table_values[i*2+1])
                       self._cache_contents[index_string] = self._file_read(self._table_values[i*2])
                       return self._cache_contents[index_string]
               raise ERROR, 'Index "%s" don\'t have value.' % index_string           
       else:#Not cache, get item from file
           for i in range(self.total):
               self._file.seek(self._table_indexs[i*2+1])
               index = self._file_read(self._table_indexs[i*2])
               if index_string == index:
                   self._file.seek(self._table_values[i*2+1])
                   return self._file_read(self._table_values[i*2])
           raise ERROR, 'Index "%s" don\'t have value.' % index_string

   #The same of get_value but return index of value
   def get_index(self, value_string):
       if self._cache_type == ALL:
           if value_string in self._cache_contents.values():
               for index, value in self._cache_contents.iteritems():
                   if value == value_string:
                       return index
           else:
               raise ERROR, 'Value "%s" don\'t have index.' % value_string
       elif self._cache_type == ALL_PROGRESSIVE:
           if value_string in self._cache_contents.values():
               for index, value in self._cache_contents.iteritems():
                   if value == value_string:
                       return index
           else:
               for i in range(self.total):
                   self._file.seek(self._table_values[i*2+1])
                   value = self._file_read(self._table_values[i*2])
                   if value_string == value:
                       self._file.seek(self._table_indexs[i*2+1])
                       index = self._file_read(self._table_indexs[i*2])
                       self._cache_contents[index] = value
                       return index             
               raise ERROR, 'Value "%s" don\'t have index.' % value_string
       else:
           for i in range(self.total):
               self._file.seek(self._table_values[i*2+1])
               value = self._file_read(self._table_values[i*2])
               if value_string == value:
                   self._file.seek(self._table_indexs[i*2+1])
                   return self._file_read(self._table_indexs[i*2])
           raise ERROR, 'Value "%s" don\'t have index.' % value_string           

   #Export data, use cache if is ALL
   def export(self, what=ALL):
       if what == ALL:
           if self._cache_type == ALL:
               return self._cache_contents
           else:
               return self._extract_all()
       elif what == INDEXS:
           if self._cache_type == ALL:
               return self._cache_contents.keys()
           else:
               return self._extract_indexs()
       elif what == VALUES:
           if self._cache_type == ALL:
               return self._cache_contents.values()
           else:
               return self._extract_values()
       else:
           raise ERROR, 'Incorrect value of what. [ALL, INDEXS, VALUES]'

Qualquer coisa, sugestão, critica que possa melhorar este código digam, porque sinseramente eu acho que isto está bom. 😁

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.