Skip to content

GabrielChaves-Dev/EmDash-PT-BR

Repository files navigation

Tradução PT-BR para EmDash Admin

traduzido

Sistema de tradução para o painel administrativo do EmDash CMS, traduzindo a interface do inglês para português brasileiro.

Visão Geral

O sistema usa uma abordagem híbrida que combina:

  • Middleware - Injeta um script JS nas páginas do admin
  • Dicionário embedded - Traduções dentro do próprio JavaScript
  • JSON externo - Traduções carregadas sob demanda (opcional)
  • MutationObserver - Traduz elementos dinâmicos do React (SPA)

Arquitetura

┌─────────────────┐     ┌──────────────┐     ┌─────────────────┐
│  Navegador      │────▶│  Middleware  │────▶│  Script i18n    │
│  (Admin UI)     │     │  (Astro)     │     │  (Client-side)  │
└─────────────────┘     └──────────────┘     └─────────────────┘
        │                                              │
        ▼                                              ▼
  ┌───────────┐                                 ┌─────────────┐
  │  React    │                                 │  Mutation   │
  │  SPA      │                                 │  Observer   │
  └───────────┘                                 └─────────────┘

Arquivos do Sistema

1. public/i18n-admin-pt-br.js (Principal)

Arquivo principal contendo todas as traduções. Estrutura:

(function() {
  'use strict';
  const Lang = 'pt-BR';
  
  const dict = {
    // Sidebar
    'Dashboard': 'Painel',
    'Pages': 'Páginas',
    'Posts': 'Publicações',
    'Users': 'Usuários',
    'Settings': 'Configurações',
    
    // Ações
    'Save': 'Salvar',
    'Delete': 'Excluir',
    'Edit': 'Editar',
    'Add': 'Adicionar',
    'Create': 'Criar',
    
    // ... centenas de traduções
  };
  
  // Função de tradução com fallback
  function translateKey(key) {
    return dict[key] ?? key;
  }
  
  // Elementos HTML que serão traduzidos
  const textOnlyTags = ['h1','h2','h3','h4','h5','h6','p','span','label','th','td','div','li','article','section','header','footer','aside','nav','main','button','a','input','textarea'];
  
  // Traduz um elemento individual
  function translateElement(el) {
    if (!el || el.nodeType !== Node.ELEMENT_NODE) return;
    if (el.dataset.translated === Lang) return;
    
    const tag = el.tagName.toLowerCase();
    if (!textOnlyTags.includes(tag) && tag !== 'select') return;
    
    const raw = el.textContent?.trim();
    const t = translateKey(raw || '');
    if (raw && t && t !== raw) {
      el.textContent = el.textContent.replace(raw, t);
      el.dataset.translated = Lang;
    }
    
    // Traduz opções de select
    if (tag === 'select') {
      Array.from(el.options).forEach(opt => {
        const optText = opt.textContent?.trim();
        const translatedOpt = translateKey(optText || '');
        if (optText && translatedOpt && translatedOpt !== optText) {
          opt.textContent = translatedOpt;
        }
      });
    }
  }
  
  // Traduz toda a página
  function translate() {
    const elements = document.querySelectorAll(textOnlyTags.join(', '));
    elements.forEach(translateElement);
  }
  
  // Intercepta navegações SPA
  const originalPushState = history.pushState;
  history.pushState = function(...args) {
    originalPushState.apply(this, args);
    setTimeout(translate, 100);
    setTimeout(translate, 500);
  };
  
  // Observa elementos dinâmicos
  const observer = new MutationObserver(() => translate());
  observer.observe(document.body, { childList: true, subtree: true });
  
  // Define idioma
  document.documentElement.lang = 'pt-BR';
  
  // Traduz imediatamente
  translate();
  setTimeout(translate, 100);
  setTimeout(translate, 500);
  
  console.log('[i18n] Camada PT-BR ativa para Admin');
})();

2. src/middleware.ts

Middleware do Astro que injeta o script de tradução nas páginas do admin:

/**
 * Middleware para injetar script de tradução PT-BR no Admin
 */
export const onRequest = async (context, next) => {
  const response = await next();
  
  // Verifica se é uma rota do admin
  if (context.url.pathname.startsWith('/_emdash/admin')) {
    const html = await response.text();
    
    // Injeta o script antes do fechamento </body>
    const injectedHtml = html.replace(
      '</body>',
      '<script src="/i18n-admin-pt-br.js" defer></script></body>'
    );
    
    return new Response(injectedHtml, {
      status: response.status,
      headers: response.headers
    });
  }
  
  return response;
};

3. astro.config.mjs

Registra o middleware na configuração do Astro:

export default defineConfig({
  // ... outras configurações
  middleware: "./src/middleware.ts",
  // ...
});

4. src/layouts/Base.astro

Define o idioma no HTML do frontend:

<html lang="pt-BR">
  <!-- ... -->
</html>

Como Adicionar Novas Traduções

1. Para traduzir novos textos

Edite public/i18n-admin-pt-br.js e adicione no objeto dict:

const dict = {
  // ... traduções existentes
  
  // Nova tradução
  'New Text': 'Novo Texto',
  'Another Text': 'Outro Texto',
};

2. Ordem recomendada

  • Organize por categoria (Sidebar, Botões, Status, etc.)
  • Mantenha em ordem alfabética dentro de cada categoria
  • Use texto em inglês como chave (o que aparece na UI)

3. Para elementos específicos

Se o texto não estiver sendo traduzido:

  1. Verifique se o elemento está na lista textOnlyTags
  2. Adicione debug no console:
    console.log('[i18n] Trying:', text, '->', translateKey(text));
  3. Verifique se a chave existe no dicionário

Troubleshooting

Tradução não aparece

  1. Verifique o console do navegador por erros
  2. Confirme que o script está sendo carregado (Network tab)
  3. Verifique se o data-translated="pt-BR" está nos elementos traduzidos

Elemento específico não traduz

  1. Verifique a tag do elemento (pode precisar adicionar à lista)
  2. Confirme que a chave existe no dicionário
  3. Teste com texto exato (case-sensitive)

Select/Option não traduz

  1. O código já inclui tradução de selects
  2. Verifique o log no console
  3. Confirme que as opções existem no dicionário

Manutenção

Dicas importantes

  1. Teste após cada adição - faça refresh da página
  2. Use texto exato - a tradução é case-sensitive
  3. Evite duplicatas - verifique se a chave já existe
  4. Console logs - use para debug

Estrutura de categorias recommended

const dict = {
  // Sidebar - Principal
  'Dashboard': 'Painel',
  'Pages': 'Páginas',
  
  // Ações - Botões
  'Save': 'Salvar',
  'Delete': 'Excluir',
  
  // Status
  'Published': 'Publicado',
  'Draft': 'Rascunho',
  
  // Campos de formulário
  'Title': 'Título',
  'Content': 'Conteúdo',
  
  // Mensagens
  'Loading': 'Carregando',
  'Error': 'Erro',
};

Licença

MIT License - Use freely in your projects.

Contribuição

Para contribuir com novas traduções:

  1. Faça fork do projeto
  2. Adicione suas traduções no dicionário
  3. Teste localmente
  4. Envie o PR

About

Tradução PT-BR para EmDash Admin

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors