init: scripts diversos (crawlers, conversores, scrapers)
This commit is contained in:
347
translate-wp-plugin/setup_glossary.py
Normal file
347
translate-wp-plugin/setup_glossary.py
Normal file
@@ -0,0 +1,347 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
setup_glossary.py — Cria/actualiza glossário DeepL para WordPress PT-PT.
|
||||
|
||||
Combina:
|
||||
1. Brand names dos plugins (mantidos sem tradução)
|
||||
2. Termos WordPress PT-PT preferidos (Settings → Definições, etc.)
|
||||
3. Plataformas sociais que DeepL traduz incorrectamente (Discord → Discórdia)
|
||||
|
||||
Uso:
|
||||
python3 setup_glossary.py # cria/actualiza e guarda ID em .env
|
||||
python3 setup_glossary.py --list # lista glossários existentes
|
||||
python3 setup_glossary.py --test # testa tradução com glossário
|
||||
|
||||
Author: Descomplicar®
|
||||
Version: 1.0.0
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Carregar .env
|
||||
_env_file = Path(__file__).parent / '.env'
|
||||
if _env_file.exists():
|
||||
for _line in _env_file.read_text().splitlines():
|
||||
if '=' in _line and not _line.startswith('#'):
|
||||
_k, _v = _line.split('=', 1)
|
||||
os.environ.setdefault(_k.strip(), _v.strip())
|
||||
|
||||
try:
|
||||
import deepl
|
||||
except ImportError:
|
||||
print("ERRO: pip3 install deepl", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
DEEPL_AUTH_KEY = os.environ.get('DEEPL_API_KEY', '')
|
||||
GLOSSARY_NAME = 'WordPress PT-PT'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. BRAND NAMES — manter exactamente como em inglês
|
||||
# ---------------------------------------------------------------------------
|
||||
BRAND_NAMES = {
|
||||
# Plugins desta biblioteca
|
||||
'AI Engine': 'AI Engine',
|
||||
'Astra': 'Astra',
|
||||
'BDThemes Element Pack': 'BDThemes Element Pack',
|
||||
'BetterDocs': 'BetterDocs',
|
||||
'Bit Integrations': 'Bit Integrations',
|
||||
'Bit Social': 'Bit Social',
|
||||
'Branda': 'Branda',
|
||||
'Docket Cache': 'Docket Cache',
|
||||
'Elementor': 'Elementor',
|
||||
'Elementor Pro': 'Elementor Pro',
|
||||
'ElementsKit': 'ElementsKit',
|
||||
'Email Candy': 'Email Candy',
|
||||
'Envato Elements': 'Envato Elements',
|
||||
'Eventin': 'Eventin',
|
||||
'FileBird': 'FileBird',
|
||||
'Fluent Booking': 'Fluent Booking',
|
||||
'FluentCRM': 'FluentCRM',
|
||||
'FluentForms': 'FluentForms',
|
||||
'Fluent Forms': 'Fluent Forms',
|
||||
'Fluent SMTP': 'Fluent SMTP',
|
||||
'Fluent Support': 'Fluent Support',
|
||||
'Forminator': 'Forminator',
|
||||
'GUM Elementor Addon': 'GUM Elementor Addon',
|
||||
'Happy Elementor Addons': 'Happy Elementor Addons',
|
||||
'HappyFiles': 'HappyFiles',
|
||||
'Insert Headers and Footers': 'Insert Headers and Footers',
|
||||
'JetEngine': 'JetEngine',
|
||||
'KiviCare': 'KiviCare',
|
||||
'Loco Translate': 'Loco Translate',
|
||||
'LoginPress': 'LoginPress',
|
||||
'MainWP': 'MainWP',
|
||||
'BackWPup': 'BackWPup',
|
||||
'MetForm': 'MetForm',
|
||||
'PowerPack Elements': 'PowerPack Elements',
|
||||
'Rank Math': 'Rank Math',
|
||||
'Real Cookie Banner': 'Real Cookie Banner',
|
||||
'Shipper': 'Shipper',
|
||||
'TablePress': 'TablePress',
|
||||
'Ultimate Branding': 'Ultimate Branding',
|
||||
'Uncanny Automator': 'Uncanny Automator',
|
||||
'UpdraftPlus': 'UpdraftPlus',
|
||||
'WebP Express': 'WebP Express',
|
||||
'WholesaleX': 'WholesaleX',
|
||||
'WooCommerce': 'WooCommerce',
|
||||
'WooCommerce Dashboard Stats': 'WooCommerce Dashboard Stats',
|
||||
'Wordfence': 'Wordfence',
|
||||
'WPCode': 'WPCode',
|
||||
'WP Defender': 'WP Defender',
|
||||
'WPForms': 'WPForms',
|
||||
'WPFunnels': 'WPFunnels',
|
||||
'WP Hummingbird': 'WP Hummingbird',
|
||||
'WP Mail SMTP': 'WP Mail SMTP',
|
||||
'WP Rocket': 'WP Rocket',
|
||||
'WP Smush': 'WP Smush',
|
||||
'WP Security Audit Log': 'WP Security Audit Log',
|
||||
'WPMU DEV': 'WPMU DEV',
|
||||
'WP-Optimize': 'WP-Optimize',
|
||||
'WP Fastest Cache': 'WP Fastest Cache',
|
||||
# Core WordPress
|
||||
'WordPress': 'WordPress',
|
||||
'Gutenberg': 'Gutenberg',
|
||||
'WP-CLI': 'WP-CLI',
|
||||
'phpMyAdmin': 'phpMyAdmin',
|
||||
# Plugins adicionais starter.descomplicar.pt
|
||||
'Complianz': 'Complianz',
|
||||
'WP Activity Log': 'WP Activity Log',
|
||||
'Meow Apps': 'Meow Apps',
|
||||
'Happy Addons': 'Happy Addons',
|
||||
# Termos AI/LLM que DeepL traduz incorrectamente
|
||||
'Playground': 'Playground',
|
||||
'Chatbot': 'Chatbot',
|
||||
'Prompt': 'Prompt',
|
||||
'Prompts': 'Prompts',
|
||||
'Token': 'Token',
|
||||
'Tokens': 'Tokens',
|
||||
'Embedding': 'Embedding',
|
||||
'Embeddings': 'Embeddings',
|
||||
'Fine-tuning': 'Ajuste fino',
|
||||
'Finetune': 'Ajuste fino',
|
||||
'MCP': 'MCP',
|
||||
# Plataformas que DeepL traduz (Discord → Discórdia, etc.)
|
||||
'Discord': 'Discord',
|
||||
'Slack': 'Slack',
|
||||
'GitHub': 'GitHub',
|
||||
'GitLab': 'GitLab',
|
||||
'Bitbucket': 'Bitbucket',
|
||||
'Zapier': 'Zapier',
|
||||
'HubSpot': 'HubSpot',
|
||||
'Mailchimp': 'Mailchimp',
|
||||
'SendGrid': 'SendGrid',
|
||||
'Twilio': 'Twilio',
|
||||
'Stripe': 'Stripe',
|
||||
'PayPal': 'PayPal',
|
||||
'Moloni': 'Moloni',
|
||||
'Multibanco': 'Multibanco',
|
||||
'Google Analytics': 'Google Analytics',
|
||||
'Google Tag Manager': 'Google Tag Manager',
|
||||
'Google Search Console': 'Google Search Console',
|
||||
'Google reCAPTCHA': 'Google reCAPTCHA',
|
||||
'Facebook Pixel': 'Facebook Pixel',
|
||||
'WhatsApp': 'WhatsApp',
|
||||
'Telegram': 'Telegram',
|
||||
'TikTok': 'TikTok',
|
||||
'LinkedIn': 'LinkedIn',
|
||||
'YouTube': 'YouTube',
|
||||
'Instagram': 'Instagram',
|
||||
'Twitter': 'Twitter',
|
||||
'Twitch': 'Twitch',
|
||||
'Pinterest': 'Pinterest',
|
||||
'Dropbox': 'Dropbox',
|
||||
'Amazon S3': 'Amazon S3',
|
||||
'Google Drive': 'Google Drive',
|
||||
'OneDrive': 'OneDrive',
|
||||
# Termos técnicos a manter em inglês
|
||||
'API': 'API',
|
||||
'JSON': 'JSON',
|
||||
'REST API': 'REST API',
|
||||
'CSS': 'CSS',
|
||||
'HTML': 'HTML',
|
||||
'PHP': 'PHP',
|
||||
'JavaScript': 'JavaScript',
|
||||
'URL': 'URL',
|
||||
'SSL': 'SSL',
|
||||
'HTTPS': 'HTTPS',
|
||||
'CDN': 'CDN',
|
||||
'DNS': 'DNS',
|
||||
'SMTP': 'SMTP',
|
||||
'IMAP': 'IMAP',
|
||||
'FTP': 'SFTP',
|
||||
'SFTP': 'SFTP',
|
||||
'OAuth': 'OAuth',
|
||||
'JWT': 'JWT',
|
||||
'SEO': 'SEO',
|
||||
'UI': 'UI',
|
||||
'UX': 'UX',
|
||||
'CRM': 'CRM',
|
||||
'SaaS': 'SaaS',
|
||||
'GDPR': 'RGPD',
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. TERMOS WORDPRESS PT-PT
|
||||
# Apenas termos críticos onde DeepL pode usar PT-BR
|
||||
# ---------------------------------------------------------------------------
|
||||
WORDPRESS_TERMS = {
|
||||
'Settings': 'Definições',
|
||||
'Password': 'Palavra-passe',
|
||||
'Dashboard': 'Painel de controlo',
|
||||
'Update': 'Actualização',
|
||||
'Updates': 'Actualizações',
|
||||
'Backup': 'Cópia de segurança',
|
||||
'Backups': 'Cópias de segurança',
|
||||
'Plugin': 'Plugin',
|
||||
'Plugins': 'Plugins',
|
||||
'Widget': 'Widget',
|
||||
'Widgets': 'Widgets',
|
||||
'Theme': 'Tema',
|
||||
'Themes': 'Temas',
|
||||
'Shortcode': 'Código curto',
|
||||
'Webhook': 'Webhook',
|
||||
'Log': 'Registo',
|
||||
'Logs': 'Registos',
|
||||
'Cache': 'Cache',
|
||||
'Firewall': 'Firewall',
|
||||
'Malware': 'Malware',
|
||||
# E-commerce
|
||||
'Cart': 'Carrinho',
|
||||
'Checkout': 'Finalização de compra',
|
||||
'Order': 'Encomenda',
|
||||
'Orders': 'Encomendas',
|
||||
'Coupon': 'Cupão',
|
||||
'Coupons': 'Cupões',
|
||||
'Stock': 'Stock',
|
||||
'Inventory': 'Inventário',
|
||||
'SKU': 'Referência',
|
||||
'VAT': 'IVA',
|
||||
# Segurança
|
||||
'Login': 'Início de sessão',
|
||||
'Logout': 'Terminar sessão',
|
||||
'Whitelist': 'Lista de permissões',
|
||||
'Blacklist': 'Lista de bloqueios',
|
||||
# Formulários
|
||||
'Checkbox': 'Caixa de seleção',
|
||||
'Dropdown': 'Lista pendente',
|
||||
'Submit': 'Submeter',
|
||||
# Acções comuns
|
||||
'Save': 'Guardar',
|
||||
'Delete': 'Eliminar',
|
||||
'Reset': 'Repor',
|
||||
'Upload': 'Carregar',
|
||||
'Download': 'Transferir',
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_all_entries() -> dict:
|
||||
entries = {}
|
||||
entries.update(BRAND_NAMES)
|
||||
entries.update(WORDPRESS_TERMS)
|
||||
return entries
|
||||
|
||||
|
||||
def list_glossaries(translator):
|
||||
glossaries = translator.list_glossaries()
|
||||
if not glossaries:
|
||||
print("Sem glossários criados.")
|
||||
return
|
||||
for g in glossaries:
|
||||
print(f" {g.name!r} — ID: {g.glossary_id} | {g.entry_count} entradas | {g.source_lang}→{g.target_lang}")
|
||||
|
||||
|
||||
def create_or_update_glossary(translator) -> str:
|
||||
entries = get_all_entries()
|
||||
print(f" Entradas a carregar: {len(entries)}")
|
||||
|
||||
# Verificar se já existe glossário com este nome e apagar
|
||||
existing = translator.list_glossaries()
|
||||
for g in existing:
|
||||
if g.name == GLOSSARY_NAME:
|
||||
print(f" Glossário existente encontrado (ID: {g.glossary_id}) — a substituir...")
|
||||
translator.delete_glossary(g.glossary_id)
|
||||
break
|
||||
|
||||
glossary = translator.create_glossary(
|
||||
GLOSSARY_NAME,
|
||||
source_lang='EN',
|
||||
target_lang='PT',
|
||||
entries=entries,
|
||||
)
|
||||
print(f" Glossário criado: {glossary.glossary_id}")
|
||||
print(f" Entradas confirmadas: {glossary.entry_count}")
|
||||
return glossary.glossary_id
|
||||
|
||||
|
||||
def save_glossary_id(glossary_id: str):
|
||||
env_path = Path(__file__).parent / '.env'
|
||||
content = env_path.read_text()
|
||||
if 'DEEPL_GLOSSARY_ID=' in content:
|
||||
lines = []
|
||||
for line in content.splitlines():
|
||||
if line.startswith('DEEPL_GLOSSARY_ID='):
|
||||
lines.append(f'DEEPL_GLOSSARY_ID={glossary_id}')
|
||||
else:
|
||||
lines.append(line)
|
||||
env_path.write_text('\n'.join(lines) + '\n')
|
||||
else:
|
||||
with open(env_path, 'a') as f:
|
||||
f.write(f'\nDEEPL_GLOSSARY_ID={glossary_id}\n')
|
||||
print(f" ID guardado em .env: DEEPL_GLOSSARY_ID={glossary_id}")
|
||||
|
||||
|
||||
def test_glossary(translator, glossary_id: str):
|
||||
test_strings = [
|
||||
'Discord notifications',
|
||||
'Go to Settings',
|
||||
'UpdraftPlus Backup',
|
||||
'Password reset',
|
||||
'WooCommerce Cart',
|
||||
'Wordfence Firewall',
|
||||
'Update available',
|
||||
]
|
||||
print(f"\n Teste de tradução com glossário:")
|
||||
results = translator.translate_text(
|
||||
test_strings,
|
||||
source_lang='EN',
|
||||
target_lang='PT-PT',
|
||||
glossary=glossary_id,
|
||||
)
|
||||
for src, res in zip(test_strings, results):
|
||||
print(f" EN: {src!r}")
|
||||
print(f" PT: {res.text!r}")
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
if not DEEPL_AUTH_KEY:
|
||||
print("ERRO: DEEPL_API_KEY não definida.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
args = sys.argv[1:]
|
||||
translator = deepl.Translator(DEEPL_AUTH_KEY)
|
||||
|
||||
if '--list' in args:
|
||||
print("\nGlossários DeepL:")
|
||||
list_glossaries(translator)
|
||||
return
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f" Setup Glossário DeepL — {GLOSSARY_NAME}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
glossary_id = create_or_update_glossary(translator)
|
||||
save_glossary_id(glossary_id)
|
||||
|
||||
if '--test' in args or True: # sempre testar
|
||||
test_glossary(translator, glossary_id)
|
||||
|
||||
print(f"\n Concluído. Usar DEEPL_GLOSSARY_ID={glossary_id}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user