style: translate error descriptions and recommended actions to Portuguese and fix word spacing
This commit is contained in:
@@ -25,23 +25,240 @@ def compile_status_codes_if_needed():
|
||||
return
|
||||
|
||||
try:
|
||||
import pypdf
|
||||
import pdfplumber
|
||||
import re
|
||||
reader = pypdf.PdfReader(PDF_FILE)
|
||||
|
||||
PHRASE_TRANSLATIONS = {
|
||||
"cannot connect on socket": "Não foi possível conectar ao socket",
|
||||
"client connection refused": "Conexão com o cliente recusada",
|
||||
"unable to allocate new media for backup, storage unit has none available": "Não foi possível alocar nova mídia para o backup; a unidade de armazenamento não tem nenhuma disponível",
|
||||
"none of the requested files were backed up": "Nenhum dos arquivos solicitados foi salvo (backup falhou)",
|
||||
"client/server handshaking failed": "Falha no handshake (aperto de mão) entre cliente e servidor",
|
||||
"snapshot error encountered": "Erro de snapshot encontrado",
|
||||
"disk is full": "O disco está cheio",
|
||||
"file open failed": "Falha ao abrir o arquivo",
|
||||
"file read failed": "Falha ao ler o arquivo",
|
||||
"file write failed": "Falha ao gravar o arquivo",
|
||||
"file close failed": "Falha ao fechar o arquivo",
|
||||
"user backup failed": "Falha no backup solicitado pelo usuário",
|
||||
"unimplemented feature": "Recurso não implementado",
|
||||
"invalid command parameter": "Parâmetro de comando inválido",
|
||||
"invalid command usage": "Uso de comando inválido",
|
||||
"request timed out": "Tempo limite da requisição esgotado",
|
||||
"system call failed": "Falha na chamada de sistema",
|
||||
"permission denied": "Permissão negada",
|
||||
"write open failed": "Falha ao abrir para gravação",
|
||||
"read open failed": "Falha ao abrir para leitura",
|
||||
"no storage units available": "Nenhuma unidade de armazenamento disponível",
|
||||
"cannot connect to server": "Não foi possível conectar ao servidor",
|
||||
"connection timed out": "Tempo limite de conexão esgotado",
|
||||
"host is unreachable": "Host/Servidor de destino inacessível",
|
||||
"network is unreachable": "Rede inacessível",
|
||||
"bad file descriptor": "Descritor de arquivo inválido",
|
||||
"no space left on device": "Sem espaço livre no dispositivo",
|
||||
"broken pipe": "Pipe quebrado (conexão interrompida)",
|
||||
"connection reset by peer": "Conexão redefinida pelo host de destino",
|
||||
"address already in use": "Endereço já em uso",
|
||||
"host is down": "O host de destino está desligado ou inacessível",
|
||||
"too many open files": "Muitos arquivos abertos no sistema",
|
||||
"file too large": "Arquivo muito grande",
|
||||
"disk quota exceeded": "Cota de disco excedida",
|
||||
"stale nfs file handle": "Manipulador de arquivo NFS obsoleto",
|
||||
"directory not empty": "O diretório não está vazio",
|
||||
"too many users": "Muitos usuários conectados",
|
||||
"process limit reached": "Limite de processos atingido",
|
||||
"operation canceled": "Operação cancelada",
|
||||
"operation now in progress": "Operação em progresso",
|
||||
"already in progress": "Já em progresso",
|
||||
"bad message": "Mensagem inválida",
|
||||
"identifier removed": "Identificador removido",
|
||||
"no data available": "Nenhum dado disponível",
|
||||
"device not configured": "Dispositivo não configurado",
|
||||
"media not present": "Mídia não inserida",
|
||||
"write protected": "Mídia protegida contra gravação",
|
||||
"hardware error": "Erro de hardware",
|
||||
"driver error": "Erro de driver de dispositivo",
|
||||
"configuration error": "Erro de configuração",
|
||||
"license key expired": "Chave de licença expirada",
|
||||
"invalid license key": "Chave de licença inválida",
|
||||
"no matching devices found": "Nenhum dispositivo correspondente encontrado",
|
||||
"device busy": "Dispositivo ocupado",
|
||||
"drive needs cleaning": "A unidade de fita precisa de limpeza",
|
||||
"tape alert detected": "Alerta de fita detectado",
|
||||
"robotic failure": "Falha na robótica (biblioteca de fitas)",
|
||||
"robotic communication failed": "Falha na comunicação com a robótica",
|
||||
"robotic device offline": "Dispositivo robótico offline",
|
||||
"volume not found": "Volume não encontrado",
|
||||
"volume in use": "Volume em uso",
|
||||
"volume is read-only": "Volume configurado como somente leitura",
|
||||
"cannot mount volume": "Não foi possível montar o volume",
|
||||
"cannot unmount volume": "Não foi possível desmontar o volume",
|
||||
"drive offline": "Unidade de drive offline",
|
||||
"drive in use": "Unidade de drive em uso",
|
||||
"drive not ready": "Unidade de drive não pronta",
|
||||
"mount failed": "Falha na montagem",
|
||||
"unmount failed": "Falha na desmontagem",
|
||||
"positioning failed": "Falha no posicionamento da fita",
|
||||
"rewind failed": "Falha ao rebobinar",
|
||||
"unload failed": "Falha ao descarregar a fita",
|
||||
"format failed": "Falha na formatação",
|
||||
"database open failed": "Falha ao abrir banco de dados",
|
||||
"database read failed": "Falha ao ler banco de dados",
|
||||
"database write failed": "Falha ao gravar banco de dados",
|
||||
"database close failed": "Falha ao fechar banco de dados",
|
||||
"active backup already running": "Backup ativo já em execução para este cliente/política",
|
||||
"the requested operation was successfully completed": "A operação solicitada foi concluída com sucesso",
|
||||
"the requested operation was partially successful": "A operação solicitada foi parcialmente bem-sucedida",
|
||||
"valid archive image produced, but no files deleted due to non-fatal problems": "Imagem de arquivo válida produzida, mas nenhum arquivo foi excluído devido a problemas não fatais",
|
||||
"archive file removal failed": "Falha na remoção do arquivo de arquivamento",
|
||||
"restore failed completely": "A restauração falhou completamente",
|
||||
"the archive failed to backup the requested files": "O arquivamento falhou ao salvar os arquivos solicitados",
|
||||
"unable to determine the status of rbak": "Incapaz de determinar o status do rbak",
|
||||
"anecessary extension package is not installed or not configured properly": "Um pacote de extensão necessário não está instalado ou configurado corretamente",
|
||||
"allocation failed": "Falha de alocação de memória",
|
||||
"system call failed": "Falha na chamada de sistema",
|
||||
"valid archive image produced but no files deleted due to nonfatal problems": "Imagem de arquivo válida produzida, mas nenhum arquivo foi excluído devido a problemas não fatais",
|
||||
"can't connect to client": "Não foi possível conectar ao cliente",
|
||||
"none of the requested connections were successful": "Nenhuma das conexões solicitadas foi bem-sucedida"
|
||||
}
|
||||
|
||||
SENTENCE_TRANSLATIONS = {
|
||||
"verify that bpcompatd, vnetd, and private branch exchange (pbx) are running.": "Verifique se os serviços bpcompatd, vnetd e Private Branch Exchange (PBX) estão em execução.",
|
||||
"verify that the required extension product is installed and configured.": "Verifique se o produto de extensão requerido está instalado e configurado.",
|
||||
"free up memory by terminating any unneeded processes that consume memory.": "Libere memória física encerrando quaisquer processos desnecessários em execução.",
|
||||
"check the alllogentries and problems reports to determine the system call that failed.": "Verifique os relatórios de 'All Log Entries' (Todos os Logs) e 'Problems' (Problemas) para determinar qual chamada de sistema falhou.",
|
||||
"if you want the path for the disk storage unit to reside in the root filesystem:": "Se você deseja que o caminho da unidade de armazenamento de disco resida no sistema de arquivos raiz:",
|
||||
"check the netbackup problems report for clues on where and why the problem occurred.": "Consulte o relatório de Problemas do NetBackup para obter pistas sobre onde e por que o problema ocorreu.",
|
||||
"check the netbackup problems report to determine the storage unit that is out of media.": "Verifique o relatório de Problemas do NetBackup para determinar qual unidade de armazenamento está sem mídia.",
|
||||
"perform the following, as appropriate:": "Execute os seguintes passos conforme apropriado:",
|
||||
"do the following, as appropriate:": "Execute os seguintes passos conforme apropriado:",
|
||||
"ensure that the appropriate plug-in is configured in the web ui with the appropriate credentials.": "Certifique-se de que o plug-in correto está configurado no painel Web com as credenciais apropriadas.",
|
||||
"try to ping the client from the server.": "Tente realizar um teste de ping bidirecional entre o servidor e o cliente.",
|
||||
"resolve network communication problems.": "Resolva os problemas de comunicação de rede e liberação de portas.",
|
||||
"no action is needed, unless a database was backed up": "Nenhuma ação é necessária, a menos que um banco de dados tenha sido copiado.",
|
||||
"a file or a directory path is more than 1023 characters long.": "O caminho de um arquivo ou diretório possui mais de 1023 caracteres.",
|
||||
"verify that you have permission to delete the files and that": "Verifique se você possui permissões de exclusão de arquivos aplicadas e que o atributo de somente leitura não está ativo.",
|
||||
"verify that you have read access to the files.": "Verifique se o usuário executor possui permissões de acesso de leitura aos arquivos.",
|
||||
"check for a new core file to see if rbak quit abnormally.": "Verifique por novos arquivos de dump (core dump) para analisar se o processo rbak terminou de forma anormal.",
|
||||
"free up space on the disks where netbackup catalogs reside": "Libere espaço livre nos volumes de disco onde residem os catálogos do NetBackup e tente a operação novamente."
|
||||
}
|
||||
|
||||
WORD_TRANSLATIONS = {
|
||||
"cannot": "não é possível", "unable": "não foi possível", "failed": "falhou", "failure": "falha",
|
||||
"connection": "conexão", "connect": "conectar", "refused": "recusada", "error": "erro", "client": "cliente",
|
||||
"server": "servidor", "socket": "socket", "disk": "disco", "full": "cheio", "file": "arquivo",
|
||||
"open": "abrir", "read": "ler", "write": "gravar", "close": "fechar", "media": "mídia",
|
||||
"storage": "armazenamento", "unit": "unidade", "available": "disponível", "none": "nenhum",
|
||||
"requested": "solicitado", "files": "arquivos", "backed": "salvo", "handshaking": "handshake",
|
||||
"snapshot": "snapshot", "encountered": "encontrado", "invalid": "inválido", "parameter": "parâmetro",
|
||||
"command": "comando", "usage": "uso", "timeout": "tempo limite esgotado", "database": "banco de dados",
|
||||
"volume": "volume", "pool": "pool", "job": "job", "running": "executando", "restore": "restauração",
|
||||
"delete": "excluir", "removal": "remoção", "user": "usuário", "permission": "permissão",
|
||||
"denied": "negada", "directory": "diretório", "path": "caminho", "unimplemented": "não implementado",
|
||||
"feature": "recurso", "empty": "vazio", "exceeded": "excedido", "limit": "limite", "device": "dispositivo",
|
||||
"busy": "ocupado", "offline": "offline", "online": "online", "network": "rede", "timed": "esgotado",
|
||||
"out": "fora", "verify": "verifique", "check": "verifique", "ensure": "garanta", "please": "por favor",
|
||||
"resolving": "resolvendo", "problems": "problemas", "action": "ação", "recommended": "recomendada",
|
||||
"the": "o", "and": "e", "or": "ou", "for": "para", "with": "com", "by": "por", "of": "de",
|
||||
"is": "está", "are": "estão", "was": "foi", "were": "foram", "that": "que", "not": "não", "no": "não",
|
||||
"an": "um", "a": "um", "following": "seguinte", "information": "informação", "applies": "aplica-se",
|
||||
"only": "apenas", "using": "usando", "contact": "contate", "your": "seu", "increase": "aumentar",
|
||||
"limit": "limite", "see": "veja", "quit": "sair", "abnormally": "anormalmente", "required": "requerido",
|
||||
"product": "produto", "installed": "instalado", "configured": "configurado", "free": "liberar",
|
||||
"memory": "memória", "terminating": "encerrando", "any": "qualquer", "unneeded": "desnecessário",
|
||||
"processes": "processos", "all": "todos", "entries": "entradas", "reports": "relatórios",
|
||||
"determine": "determinar", "want": "desejar", "reside": "residir", "root": "raiz", "filesystem": "sistema de arquivos",
|
||||
"report": "relatório", "clues": "pistas", "where": "onde", "why": "por que", "problem": "problema",
|
||||
"occurred": "ocorreu", "perform": "executar", "as": "como"
|
||||
}
|
||||
|
||||
def translate_sentence(text):
|
||||
if not text:
|
||||
return ""
|
||||
clean_txt = text.strip()
|
||||
lower_txt = clean_txt.lower().replace(" ", " ")
|
||||
lookup_txt = lower_txt.rstrip(".")
|
||||
|
||||
if lookup_txt in PHRASE_TRANSLATIONS:
|
||||
res = PHRASE_TRANSLATIONS[lookup_txt]
|
||||
if lower_txt.endswith("."):
|
||||
res += "."
|
||||
return res
|
||||
if lookup_txt in SENTENCE_TRANSLATIONS:
|
||||
res = SENTENCE_TRANSLATIONS[lookup_txt]
|
||||
if lower_txt.endswith("."):
|
||||
res += "."
|
||||
return res
|
||||
|
||||
bullet_match = re.match(r'^([■•\-\*]\s*)(.*)', clean_txt)
|
||||
if bullet_match:
|
||||
bullet_symbol = bullet_match.group(1)
|
||||
sub_text = bullet_match.group(2)
|
||||
return bullet_symbol + translate_sentence(sub_text)
|
||||
|
||||
words = clean_txt.split()
|
||||
translated_words = []
|
||||
for w in words:
|
||||
w_clean = re.sub(r'[^a-zA-Z\']', '', w).lower()
|
||||
if w_clean in WORD_TRANSLATIONS:
|
||||
trans = WORD_TRANSLATIONS[w_clean]
|
||||
w_trans = w.lower().replace(w_clean, trans)
|
||||
if w[0].isupper():
|
||||
w_trans = w_trans.capitalize()
|
||||
translated_words.append(w_trans)
|
||||
else:
|
||||
translated_words.append(w)
|
||||
return " ".join(translated_words)
|
||||
|
||||
def translate_text(multiline_text):
|
||||
if not multiline_text:
|
||||
return ""
|
||||
lines = multiline_text.splitlines()
|
||||
translated_lines = [translate_sentence(line) for line in lines]
|
||||
return "\n".join(translated_lines)
|
||||
|
||||
def clean_spacing(text):
|
||||
if not text:
|
||||
return ""
|
||||
return re.sub(r'\s+', ' ', text).strip()
|
||||
|
||||
def get_first_action(action_text):
|
||||
if not action_text:
|
||||
return "Nenhuma ação recomendada específica encontrada no manual."
|
||||
lines = [line.strip() for line in action_text.splitlines() if line.strip()]
|
||||
if not lines:
|
||||
return "Nenhuma ação recomendada específica encontrada no manual."
|
||||
bullets = ['■', '-', '*', '•']
|
||||
first_bullet = None
|
||||
for line in lines:
|
||||
if any(line.startswith(b) for b in bullets) or re.match(r'^\d+\.', line):
|
||||
cleaned_line = line
|
||||
for b in bullets:
|
||||
if cleaned_line.startswith(b):
|
||||
cleaned_line = cleaned_line[len(b):].strip()
|
||||
break
|
||||
first_bullet = cleaned_line
|
||||
break
|
||||
if first_bullet:
|
||||
return first_bullet
|
||||
for line in lines:
|
||||
if line.endswith(':') and len(line) < 40:
|
||||
continue
|
||||
return line
|
||||
return lines[0]
|
||||
|
||||
parsed = {}
|
||||
with pdfplumber.open(PDF_FILE) as pdf:
|
||||
full_text_list = []
|
||||
for page in reader.pages:
|
||||
text = page.extract_text()
|
||||
for page in pdf.pages:
|
||||
text = page.extract_text(x_tolerance=2.0)
|
||||
if text:
|
||||
full_text_list.append(text)
|
||||
full_text = "\n".join(full_text_list)
|
||||
|
||||
# Parse status codes
|
||||
pattern = re.compile(r'NetBackup\s*status\s*code\s*:\s*(\d+)', re.IGNORECASE)
|
||||
matches = list(pattern.finditer(full_text))
|
||||
|
||||
parsed = {}
|
||||
bullets = ['■', '-', '*', '•']
|
||||
|
||||
for idx, match in enumerate(matches):
|
||||
code_str = match.group(1)
|
||||
code_num = int(code_str)
|
||||
@@ -49,7 +266,6 @@ def compile_status_codes_if_needed():
|
||||
end_pos = matches[idx + 1].start() if idx + 1 < len(matches) else len(full_text)
|
||||
|
||||
chunk = full_text[start_pos:end_pos]
|
||||
|
||||
msg_match = re.search(r'Message\s*:\s*(.*)', chunk, re.IGNORECASE)
|
||||
if msg_match:
|
||||
expl_match = re.search(r'Explanation\s*:\s*', chunk, re.IGNORECASE)
|
||||
@@ -61,7 +277,7 @@ def compile_status_codes_if_needed():
|
||||
desc = chunk[msg_start:expl_match.start()].strip()
|
||||
else:
|
||||
desc = chunk[msg_start:].strip()
|
||||
desc = re.sub(r'\s+', ' ', desc).strip()
|
||||
desc = clean_spacing(desc)
|
||||
|
||||
rec_match = re.search(r'Recommended\s*Action\s*:\s*', chunk, re.IGNORECASE)
|
||||
action_full = ""
|
||||
@@ -82,33 +298,21 @@ def compile_status_codes_if_needed():
|
||||
lines = [line.strip() for line in action_full.splitlines() if line.strip()]
|
||||
action_clean = "\n".join(lines)
|
||||
|
||||
# Get first action
|
||||
first_action = "No specific recommended action found in the manual."
|
||||
if lines:
|
||||
first_bullet = None
|
||||
for line in lines:
|
||||
if any(line.startswith(b) for b in bullets) or re.match(r'^\d+\.', line):
|
||||
cleaned_line = line
|
||||
for b in bullets:
|
||||
if cleaned_line.startswith(b):
|
||||
cleaned_line = cleaned_line[len(b):].strip()
|
||||
break
|
||||
first_bullet = cleaned_line
|
||||
break
|
||||
if first_bullet:
|
||||
first_action = first_bullet
|
||||
else:
|
||||
for line in lines:
|
||||
if line.endswith(':') and len(line) < 40:
|
||||
continue
|
||||
first_action = line
|
||||
break
|
||||
desc_pt = translate_sentence(desc)
|
||||
action_clean_pt = translate_text(action_clean)
|
||||
first_action_eng = get_first_action(action_clean)
|
||||
first_action_pt = translate_sentence(first_action_eng)
|
||||
|
||||
if desc_pt and desc_pt[0].islower():
|
||||
desc_pt = desc_pt[0].upper() + desc_pt[1:]
|
||||
if first_action_pt and first_action_pt[0].islower():
|
||||
first_action_pt = first_action_pt[0].upper() + first_action_pt[1:]
|
||||
|
||||
parsed[code_num] = {
|
||||
"code": code_num,
|
||||
"desc": desc,
|
||||
"first_action": first_action,
|
||||
"full_action": action_clean
|
||||
"desc": desc_pt,
|
||||
"first_action": first_action_pt,
|
||||
"full_action": action_clean_pt
|
||||
}
|
||||
|
||||
with open(STATUS_CODES_FILE, "w", encoding="utf-8") as f:
|
||||
@@ -116,6 +320,7 @@ def compile_status_codes_if_needed():
|
||||
except Exception as e:
|
||||
print(f"Error compiling status codes: {e}")
|
||||
|
||||
|
||||
# Compile on load if needed
|
||||
compile_status_codes_if_needed()
|
||||
|
||||
|
||||
+8533
-8533
File diff suppressed because one or more lines are too long
@@ -3,3 +3,5 @@ pandas
|
||||
plotly
|
||||
fpdf2
|
||||
pypdf
|
||||
pdfplumber
|
||||
|
||||
|
||||
Reference in New Issue
Block a user