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
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pypdf
|
import pdfplumber
|
||||||
import re
|
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 = []
|
full_text_list = []
|
||||||
for page in reader.pages:
|
for page in pdf.pages:
|
||||||
text = page.extract_text()
|
text = page.extract_text(x_tolerance=2.0)
|
||||||
if text:
|
if text:
|
||||||
full_text_list.append(text)
|
full_text_list.append(text)
|
||||||
full_text = "\n".join(full_text_list)
|
full_text = "\n".join(full_text_list)
|
||||||
|
|
||||||
# Parse status codes
|
|
||||||
pattern = re.compile(r'NetBackup\s*status\s*code\s*:\s*(\d+)', re.IGNORECASE)
|
pattern = re.compile(r'NetBackup\s*status\s*code\s*:\s*(\d+)', re.IGNORECASE)
|
||||||
matches = list(pattern.finditer(full_text))
|
matches = list(pattern.finditer(full_text))
|
||||||
|
|
||||||
parsed = {}
|
|
||||||
bullets = ['■', '-', '*', '•']
|
|
||||||
|
|
||||||
for idx, match in enumerate(matches):
|
for idx, match in enumerate(matches):
|
||||||
code_str = match.group(1)
|
code_str = match.group(1)
|
||||||
code_num = int(code_str)
|
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)
|
end_pos = matches[idx + 1].start() if idx + 1 < len(matches) else len(full_text)
|
||||||
|
|
||||||
chunk = full_text[start_pos:end_pos]
|
chunk = full_text[start_pos:end_pos]
|
||||||
|
|
||||||
msg_match = re.search(r'Message\s*:\s*(.*)', chunk, re.IGNORECASE)
|
msg_match = re.search(r'Message\s*:\s*(.*)', chunk, re.IGNORECASE)
|
||||||
if msg_match:
|
if msg_match:
|
||||||
expl_match = re.search(r'Explanation\s*:\s*', chunk, re.IGNORECASE)
|
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()
|
desc = chunk[msg_start:expl_match.start()].strip()
|
||||||
else:
|
else:
|
||||||
desc = chunk[msg_start:].strip()
|
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)
|
rec_match = re.search(r'Recommended\s*Action\s*:\s*', chunk, re.IGNORECASE)
|
||||||
action_full = ""
|
action_full = ""
|
||||||
@@ -82,33 +298,21 @@ def compile_status_codes_if_needed():
|
|||||||
lines = [line.strip() for line in action_full.splitlines() if line.strip()]
|
lines = [line.strip() for line in action_full.splitlines() if line.strip()]
|
||||||
action_clean = "\n".join(lines)
|
action_clean = "\n".join(lines)
|
||||||
|
|
||||||
# Get first action
|
desc_pt = translate_sentence(desc)
|
||||||
first_action = "No specific recommended action found in the manual."
|
action_clean_pt = translate_text(action_clean)
|
||||||
if lines:
|
first_action_eng = get_first_action(action_clean)
|
||||||
first_bullet = None
|
first_action_pt = translate_sentence(first_action_eng)
|
||||||
for line in lines:
|
|
||||||
if any(line.startswith(b) for b in bullets) or re.match(r'^\d+\.', line):
|
if desc_pt and desc_pt[0].islower():
|
||||||
cleaned_line = line
|
desc_pt = desc_pt[0].upper() + desc_pt[1:]
|
||||||
for b in bullets:
|
if first_action_pt and first_action_pt[0].islower():
|
||||||
if cleaned_line.startswith(b):
|
first_action_pt = first_action_pt[0].upper() + first_action_pt[1:]
|
||||||
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
|
|
||||||
|
|
||||||
parsed[code_num] = {
|
parsed[code_num] = {
|
||||||
"code": code_num,
|
"code": code_num,
|
||||||
"desc": desc,
|
"desc": desc_pt,
|
||||||
"first_action": first_action,
|
"first_action": first_action_pt,
|
||||||
"full_action": action_clean
|
"full_action": action_clean_pt
|
||||||
}
|
}
|
||||||
|
|
||||||
with open(STATUS_CODES_FILE, "w", encoding="utf-8") as f:
|
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:
|
except Exception as e:
|
||||||
print(f"Error compiling status codes: {e}")
|
print(f"Error compiling status codes: {e}")
|
||||||
|
|
||||||
|
|
||||||
# Compile on load if needed
|
# Compile on load if needed
|
||||||
compile_status_codes_if_needed()
|
compile_status_codes_if_needed()
|
||||||
|
|
||||||
|
|||||||
+8406
-8406
File diff suppressed because one or more lines are too long
@@ -3,3 +3,5 @@ pandas
|
|||||||
plotly
|
plotly
|
||||||
fpdf2
|
fpdf2
|
||||||
pypdf
|
pypdf
|
||||||
|
pdfplumber
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user