• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

fnds

[Python] GetText

2 mensagens neste tópico

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. :cheesygrin:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Exemplo de uso:

from GetText import *
_ = GetText('file.mo', ALL).get_value

print _('Hello')

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora