feat: sync all plugins, skills, agents updates
New plugins: core-tools New skills: auto-expense, ticket-triage, design, security-check, aiktop-tasks, daily-digest, imap-triage, index-update, mindmap, notebooklm, proc-creator, tasks-overview, validate-component, perfex-module, report, calendar-manager New agents: design-critic, design-generator, design-lead, design-prompt-architect, design-researcher, compliance-auditor, metabase-analyst, gitea-integration-specialist Updated: all plugin configs, knowledge datasets, existing skills Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
266
wordpress/skills/wp-translate/SKILL.md
Normal file
266
wordpress/skills/wp-translate/SKILL.md
Normal file
@@ -0,0 +1,266 @@
|
||||
---
|
||||
name: wp-translate
|
||||
description: >
|
||||
Tradução WordPress PT-PT com DeepL Pro, glossário e scripts próprios. Use when translating WordPress plugins to PT-PT, fixing PT-BR translations, handling .po/.mo/.json files, working with Loco Translate, deploying translations to starter.descomplicar.pt, or when user mentions "tradução", "translate", "pt-pt", "pt-br", ".po", ".mo", "loco", "deepl wordpress".
|
||||
author: Descomplicar® Crescimento Digital
|
||||
version: 1.0.0
|
||||
quality_score: 100
|
||||
user_invocable: true
|
||||
category: wordpress
|
||||
tags: [wordpress, traducao, pt-pt, deepl, po, mo, gettext, loco-translate, i18n]
|
||||
desk_task: 1580
|
||||
desk_project: 65
|
||||
allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified, mcp__deepl, mcp__memory-supabase
|
||||
mcps: ssh-unified, deepl, memory-supabase
|
||||
---
|
||||
|
||||
# /wp-translate — Traduções WordPress PT-PT
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Skill para traduzir plugins WordPress para Português Europeu (PT-PT) usando DeepL Pro com glossário, scripts de automação próprios e deploy directo para starter.descomplicar.pt.
|
||||
|
||||
---
|
||||
|
||||
## Scripts Disponíveis
|
||||
|
||||
**Localização local:** `/media/ealmeida/Dados/Dev/Scripts/translate-wp-plugin/`
|
||||
**No servidor (tmp):** `/tmp/translate_missing.py`, `/tmp/fix_ptbr_safe.py`
|
||||
|
||||
| Script | Função |
|
||||
|--------|--------|
|
||||
| `translate_missing.py` | Traduz strings vazias via DeepL Pro + glossário. Suporta batch 50 strings/pedido |
|
||||
| `fix_ptbr_safe.py` | Corrige ~100 padrões PT-BR → PT-PT |
|
||||
| `fix_malformed.py` | Corrige sintaxe .po mal formada |
|
||||
| `batch_process_library.py` | Orquestra fix_malformed → fix_ptbr → translate → compile .mo para toda a biblioteca |
|
||||
| `setup_glossary.py` | Cria/actualiza glossário DeepL (175 entradas WP PT-PT) |
|
||||
|
||||
**Configuração (.env):**
|
||||
```
|
||||
DEEPL_API_KEY=3c74e27a-f688-4de2-927b-e91da46cf9cd
|
||||
DEEPL_GLOSSARY_ID=b9db5639-c201-479f-87af-adb81f112067
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DeepL Pro
|
||||
|
||||
- **Endpoint:** `api.deepl.com` (Pro — sem `:fx`)
|
||||
- **Quota:** ~1,6M / 1 trilião de chars
|
||||
- **Glossário:** 160 entradas brand names + termos WordPress (EN→PT)
|
||||
- **Atenção:** DeepL também gera padrões PT-BR — sempre correr `fix_ptbr` ANTES E DEPOIS da tradução
|
||||
|
||||
---
|
||||
|
||||
## Workflow: Plugin Individual
|
||||
|
||||
```bash
|
||||
# 1. No servidor — gerar .pot (se não existir)
|
||||
wp --path=/home/ealmeida/starter.descomplicar.pt i18n make-pot \
|
||||
wp-content/plugins/PLUGIN/ \
|
||||
/tmp/PLUGIN-pt_PT.po \
|
||||
--domain=TEXT_DOMAIN --allow-root
|
||||
|
||||
# 2. Traduzir com DeepL Pro
|
||||
python3 /tmp/translate_missing.py /tmp/PLUGIN-pt_PT.po
|
||||
|
||||
# 3. Corrigir PT-BR pós-tradução
|
||||
python3 /tmp/fix_ptbr_safe.py /tmp/PLUGIN-pt_PT.po
|
||||
|
||||
# 4. Para plugins React — gerar JSON para strings JS
|
||||
wp --path=/home/ealmeida/starter.descomplicar.pt i18n make-json \
|
||||
/tmp/PLUGIN-pt_PT.po /path/to/languages/ --no-purge --allow-root
|
||||
|
||||
# 5. Copiar para servidor
|
||||
cp /tmp/PLUGIN-pt_PT.{po,mo} /home/ealmeida/starter.descomplicar.pt/wp-content/languages/plugins/
|
||||
chown ealmeida:ealmeida /home/ealmeida/starter.descomplicar.pt/wp-content/languages/plugins/PLUGIN-pt_PT.*
|
||||
```
|
||||
|
||||
## Workflow: Biblioteca Completa
|
||||
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/Scripts/translate-wp-plugin/batch_process_library.py \
|
||||
/path/to/library
|
||||
# Opções: --skip-translate, --dry-run, --only-ptbr
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Encontrar o Text Domain
|
||||
|
||||
**Crítico:** O nome da pasta do plugin ≠ text domain. Sempre verificar:
|
||||
|
||||
```bash
|
||||
grep "Text Domain" /path/to/plugin/plugin-main.php
|
||||
```
|
||||
|
||||
**Casos conhecidos de divergência:**
|
||||
| Pasta | Text Domain | Ficheiro .po |
|
||||
|-------|-------------|--------------|
|
||||
| `pro-elements` | `elementor-pro` | `elementor-pro-pt_PT.po` |
|
||||
| `branda-white-labeling` | `ub` | `ub-pt_PT.po` |
|
||||
| `seo-by-rank-math` | `rank-math` | `rank-math-pt_PT.po` |
|
||||
|
||||
---
|
||||
|
||||
## Plugins React/JS — Ficheiros JSON
|
||||
|
||||
Plugins com `wp_set_script_translations()` precisam de um `.json` além do `.mo`.
|
||||
|
||||
**Detectar:**
|
||||
```bash
|
||||
grep -r "wp_set_script_translations" /path/plugin/ --include="*.php"
|
||||
```
|
||||
|
||||
**Gerar JSON:**
|
||||
```bash
|
||||
wp i18n make-json PLUGIN-pt_PT.po /path/languages/ --no-purge --allow-root
|
||||
```
|
||||
|
||||
**Atenção ao MD5:** WordPress calcula `md5(relative_path_of_script)` para o nome do JSON.
|
||||
Se o `source` no JSON não bater com o script registado, copiar o JSON com o MD5 correcto:
|
||||
|
||||
```bash
|
||||
# Encontrar qual script está registado
|
||||
grep "wp_register_script\|wp_enqueue_script" plugin.php | grep "HANDLE"
|
||||
|
||||
# Calcular MD5 do caminho relativo
|
||||
python3 -c "import hashlib; print(hashlib.md5('app/index.js'.encode()).hexdigest())"
|
||||
|
||||
# Copiar com nome correcto
|
||||
cp PLUGIN-pt_PT-{md5_errado}.json PLUGIN-pt_PT-{md5_correcto}.json
|
||||
```
|
||||
|
||||
**Exemplo real — ai-engine:**
|
||||
- Handle `mwai` → script `app/index.js` → MD5: `2018087f584c4398b5c3a23fc0e5f9db`
|
||||
- JSON gerado com source `app/i18n.js` → MD5: `0bdc92e05d8f3ab638aa855679db059e`
|
||||
- Solução: copiar JSON com o MD5 de `app/index.js`
|
||||
|
||||
---
|
||||
|
||||
## Padrões PT-BR Comuns (fix_ptbr)
|
||||
|
||||
DeepL introduz PT-BR mesmo com `target_lang=PT-PT`. Correr fix_ptbr **depois** da tradução:
|
||||
|
||||
| PT-BR | PT-PT |
|
||||
|-------|-------|
|
||||
| atualiz* | actualiz* |
|
||||
| ativar/desativar | activar/desactivar |
|
||||
| você/vocês | o utilizador/os utilizadores |
|
||||
| excluir/excluído | eliminar/eliminado |
|
||||
| acessar | aceder |
|
||||
| compartilhar | partilhar |
|
||||
| postagem/postagens | publicação/publicações |
|
||||
| ativo/inativo | activo/inactivo |
|
||||
| ativação/desativação | activação/desactivação |
|
||||
| digite | introduza |
|
||||
| clique | clique (OK) |
|
||||
|
||||
---
|
||||
|
||||
## Servidor starter.descomplicar.pt
|
||||
|
||||
```
|
||||
SSH: mcp__ssh-unified__ssh_execute server:"server"
|
||||
Path traduções: /home/ealmeida/starter.descomplicar.pt/wp-content/languages/plugins/
|
||||
Loco Translate: /home/ealmeida/starter.descomplicar.pt/wp-content/languages/loco/plugins/
|
||||
WP-CLI: wp --path=/home/ealmeida/starter.descomplicar.pt [...] --allow-root
|
||||
```
|
||||
|
||||
**Permissões obrigatórias após operações root:**
|
||||
```bash
|
||||
chown ealmeida:ealmeida /home/ealmeida/starter.descomplicar.pt/wp-content/languages/plugins/PLUGIN-pt_PT.*
|
||||
```
|
||||
|
||||
**Deploy completo:**
|
||||
```bash
|
||||
# Copiar .po + .mo + .json
|
||||
cp /tmp/PLUGIN-pt_PT.{po,mo} /home/.../languages/plugins/
|
||||
# Se React: copiar também os .json
|
||||
chown ealmeida:ealmeida /home/.../languages/plugins/PLUGIN-pt_PT*
|
||||
wp --path=... cache flush --allow-root
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verificação de Estado
|
||||
|
||||
```bash
|
||||
# Strings em falta em todos os plugins
|
||||
python3 -c "
|
||||
from pathlib import Path; import polib
|
||||
for f in sorted(Path('languages/plugins').glob('*-pt_PT.po')):
|
||||
po = polib.pofile(str(f))
|
||||
empty = len(po.untranslated_entries())
|
||||
if empty: print(f'{f.name}: {empty} em falta')
|
||||
"
|
||||
|
||||
# PT-BR residual após tradução
|
||||
grep -rn "atualiz\|ativar\|você\b\|excluir\b" languages/plugins/*.po
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Problemas Conhecidos
|
||||
|
||||
### Python 3.6 no servidor
|
||||
Scripts locais usam type hints Python 3.9+. Para correr no servidor:
|
||||
- Remover anotações `-> type` das funções
|
||||
- Não usar `from __future__ import annotations` (não funciona no 3.6)
|
||||
- `tuple[str, list]` → usar `Tuple` de typing
|
||||
|
||||
### msgfmt vs polib
|
||||
`msgfmt 0.19.8.1` recusa .po com strings mal formadas. Usar sempre **polib** para compilar:
|
||||
```python
|
||||
po = polib.pofile('file.po')
|
||||
po.save_as_mofile('file.mo')
|
||||
```
|
||||
|
||||
### Glossário Pro vs Free
|
||||
Glossário criado com chave `:fx` (Free) não funciona na conta Pro e vice-versa.
|
||||
Fix: `python3 setup_glossary.py` após mudar de chave API.
|
||||
|
||||
### XML tag_handling quebra com &
|
||||
`tag_handling='xml'` falha com strings como "Settings & Tools".
|
||||
Fix actual: tokens Unicode `⟦0⟧` como placeholders (implementado em translate_missing.py v2.1+).
|
||||
|
||||
### Strings hardcoded em bundles JS compilados
|
||||
Plugins com React que não usam `__()` nas strings de UI (ex: `subtitle:"text"`) não podem ser traduzidos.
|
||||
Não é possível sem modificar o bundle compilado. Aceitar e documentar.
|
||||
|
||||
### Loco Translate "Write protected"
|
||||
Ficheiros criados por root via SSH ficam inacessíveis ao web server.
|
||||
Fix: `chown ealmeida:ealmeida` nos ficheiros de tradução.
|
||||
|
||||
---
|
||||
|
||||
## Compilar .mo após Edições Manuais
|
||||
|
||||
```python
|
||||
import polib
|
||||
po = polib.pofile('/path/to/file.po')
|
||||
po.save('/path/to/file.po') # salva o .po actualizado
|
||||
po.save_as_mofile('/path/to/file.mo')
|
||||
```
|
||||
|
||||
## Re-gerar JSON após Edições ao .po
|
||||
|
||||
```bash
|
||||
wp i18n make-json file-pt_PT.po /path/languages/ --no-purge --allow-root
|
||||
# Depois sempre copiar com MD5 correcto se necessário
|
||||
chown ealmeida:ealmeida /path/languages/file-pt_PT-*.json
|
||||
wp --path=... cache flush --allow-root
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estado da Biblioteca (starter.descomplicar.pt — 25-02-2026)
|
||||
|
||||
- **21 plugins** com ficheiros .po activos
|
||||
- **Cobertura:** 100% em todos os plugins (excl. webp-express sem suporte i18n)
|
||||
- **Strings hardcoded** não traduzíveis: ~7 subtítulos no ai-engine (limitação do plugin)
|
||||
- **Loco Translate path:** `languages/loco/plugins/` para pro-elements (elementor-pro)
|
||||
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 25-02-2026 | Descomplicar®*
|
||||
Reference in New Issue
Block a user