Skip to content

fix: Internacionalização de nomes de idiomas nos menus de artigos#373

Open
Rossi-Luciano wants to merge 2 commits intoscieloorg:masterfrom
Rossi-Luciano:fix/language-menu-i18n
Open

fix: Internacionalização de nomes de idiomas nos menus de artigos#373
Rossi-Luciano wants to merge 2 commits intoscieloorg:masterfrom
Rossi-Luciano:fix/language-menu-i18n

Conversation

@Rossi-Luciano
Copy link
Contributor

O que esse PR faz?

Este PR resolve o problema de internacionalização onde idiomas além de português, inglês e espanhol apareciam como códigos ISO brutos nos menus de artigos, em vez de nomes traduzidos de acordo com o idioma da interface do usuário.

Problemas resolvidos:

  • Idiomas como alemão (de), francês (fr), russo (ru) apareciam apenas como códigos ISO
  • Nomes não eram traduzidos conforme o idioma da interface (pt/en/es)
  • IDs HTML duplicados no template de PDF causavam erros de validação

Features implementadas:

Resultado:

  • Interface PT: Resumo (Alemão), Texto (Francês), PDF (Russo)
  • Interface EN: Abstract (German), Text (French), PDF (Russian)
  • Interface ES: Resumen (Alemán), Texto (Francés), PDF (Ruso)

Onde a revisão poderia começar?

Ordem sugerida de revisão:

  1. webapp/choices.py

    • Novo dicionário: LANGUAGE_TRANSLATIONS
    • Estrutura: {codigo_iso: {idioma_interface: nome_traduzido}}
    • Verifica uso correto de lazy_gettext para i18n
    • Valida cobertura de idiomas (40+ idiomas cadastrados)
  2. webapp/utils/utils.py

    • Nova função: get_language_name(lang_code, interface_lang='en')
    • Nova função: get_language_code_upper(lang_code)
    • Nova função: register_language_filters(app)
    • Verifica lógica de fallback para idiomas não cadastrados
  3. webapp/templates/levelMenu_abstracts.html

  4. webapp/templates/levelMenu_texts.html

    • Mesmas verificações do template de abstracts
    • Validar lógica condicional de exibição
  5. webapp/templates/levelMenu_pdf.html

    • Verificar correção de IDs duplicados:
      • btnGroupDropPDFSingle para PDF único
      • btnGroupDropPDFMultiple para múltiplos PDFs
    • Validar referências ARIA labelledby correspondentes

Como este poderia ser testado manualmente?

Pré-requisitos:

# 1. Aplicar o PR
git checkout fix/language-menu-i18n

# 2. Garantir que register_language_filters() está sendo chamado
# Verificar em webapp/__init__.py:
# from webapp.utils.utils import register_language_filters
# register_language_filters(app)

# 3. Reiniciar aplicação
docker compose restart opac_webapp

# 4. Aguardar containers ficarem healthy
docker compose ps

Teste 1: Verificar tradução em português

  1. Configurar navegador para português (chrome://settings/languages)
  2. Acessar artigo com múltiplos idiomas (ex: artigo com de, fr, ru)
  3. Verificar menu RESUMO: deve mostrar "Resumo (Alemão)", "Resumo (Francês)"
  4. Verificar menu TEXTO: botão colapsado deve mostrar "(DE)", dropdown deve mostrar "Texto (Alemão)"
  5. Verificar menu PDF: deve mostrar "Download PDF (Francês)"

Teste 2: Verificar tradução em inglês

  1. Configurar navegador para inglês
  2. Acessar o mesmo artigo
  3. Verificar que nomes aparecem em inglês:
    • "Abstract (German)", "Abstract (French)"
    • "Text (DE)" (colapsado), "Text (German)" (expandido)
    • "Download PDF (Russian)"

Teste 3: Verificar tradução em espanhol

  1. Configurar navegador para espanhol
  2. Verificar nomes em espanhol:
    • "Resumen (Alemán)", "Resumen (Francés)"
    • "Texto (Alemán)", "PDF (Ruso)"

Teste 4: Testar alternância de idioma

  1. Com navegador em PT, acessar artigo
  2. Clicar no seletor de idioma (canto superior)
  3. Mudar para EN ou ES
  4. Verificar que nomes de idiomas mudam imediatamente

Teste 5: Validar HTML (IDs únicos)

  1. Acessar artigo com múltiplos PDFs
  2. Abrir DevTools (F12) → Elements
  3. Buscar por btnGroupDropPDF
  4. Verificar que existem IDs únicos:
    • btnGroupDropPDFSingle OU
    • btnGroupDropPDFMultiple
  5. Validar com validator.w3.org - não deve reportar IDs duplicados

Teste 6: Fallback para idioma desconhecido

  1. Adicionar artigo com idioma não cadastrado (ex: "xx")
  2. Verificar que aparece código em maiúsculo: "Resumo (XX)"
  3. Confirma que não quebra a interface

Teste 7: Verificar cache CDN (se aplicável)

  1. Limpar cache do BunnyCDN/Varnish
  2. Acessar artigo em PT
  3. Acessar mesmo artigo em EN
  4. Verificar que versões cacheadas são diferentes (não há conflito)

Algum cenário de contexto que queira dar?

Contexto do Problema

O site www.scielo.br publica artigos científicos em diversos idiomas além de português, inglês e espanhol. Periódicos internacionais frequentemente incluem resumos, textos completos e PDFs em idiomas como alemão, francês, russo, japonês, chinês, entre outros.

Sistema anterior (hardcoded):

# Template antigo
{% if lang == 'es' %}
  ({% trans %}Espanhol{% endtrans %})
{% elif lang == 'en' %}
  ({% trans %}Inglês{% endtrans %})
{% elif lang == 'pt' %}
  ({% trans %}Português{% endtrans %})
{% else %}
  ({{ lang }})  # ← Código ISO bruto (de, fr, ru)
{% endif %}

Problemas:

  • Usuário via "Resumo (de)" em vez de "Resumo (Alemão)"
  • Experiência inconsistente: alguns idiomas traduzidos, outros não
  • Manutenibilidade: adicionar novo idioma exigia modificar todos os templates
  • Não profissional para plataforma acadêmica internacional

Solução implementada:

  • Dicionário centralizado extensível (40+ idiomas)
  • Tradução automática via filtro Jinja2
  • Facilita adição de novos idiomas (apenas 1 arquivo)
  • Consistência em toda a interface

Alinhamento com PR #370

Este PR está preparado para o PR #370 que migra detecção de idioma de cookies para Accept-Language header:

  • Usa g.interface_language em vez de session.get('lang')
  • Não adiciona novos cookies
  • Compatível com cache de CDN (BunnyCDN/Varnish)
  • Suporta Vary: Accept-Language em vez de Vary: Cookie

Impacto nos Usuários

Pesquisadores internacionais:

  • Identificam facilmente idiomas disponíveis
  • Interface mais profissional e intuitiva
  • Não precisam conhecer códigos ISO

Editores de periódicos:

  • Melhor apresentação de conteúdo multilíngue
  • Facilita publicação de artigos internacionais
  • Menos suporte técnico sobre "o que é 'de'?"

Desenvolvedores:

  • Código mais limpo e manutenível
  • Fácil adicionar novos idiomas
  • Lógica centralizada

Screenshots

Antes (Problema)

Interface em Português:

┌─────────────────────────┐
│ Resumo (de)         ▼   │  ← Código ISO bruto
├─────────────────────────┤
│ Resumo (pt)             │
│ Resumo (en)             │
│ Resumo (de)             │  ← Não traduzido
│ Resumo (fr)             │  ← Não traduzido
└─────────────────────────┘

Interface em Inglês:

┌─────────────────────────┐
│ Abstract (de)       ▼   │  ← Ainda código ISO
├─────────────────────────┤
│ Abstract (Portuguese)   │
│ Abstract (English)      │
│ Abstract (de)           │  ← Não traduzido
│ Abstract (fr)           │  ← Não traduzido
└─────────────────────────┘

Depois (Corrigido)

Interface em Português:

┌─────────────────────────┐
│ Resumo (DE)         ▼   │  ← Código ISO maiúsculo
├─────────────────────────┤
│ Resumo (Português)      │
│ Resumo (Inglês)         │
│ Resumo (Alemão)         │  ← Traduzido! ✓
│ Resumo (Francês)        │  ← Traduzido! ✓
└─────────────────────────┘

Interface em Inglês:

┌─────────────────────────┐
│ Abstract (DE)       ▼   │  ← Código ISO maiúsculo
├─────────────────────────┤
│ Abstract (Portuguese)   │
│ Abstract (English)      │
│ Abstract (German)       │  ← Traduzido! ✓
│ Abstract (French)       │  ← Traduzido! ✓
└─────────────────────────┘

Interface em Espanhol:

┌─────────────────────────┐
│ Resumen (DE)        ▼   │  ← Código ISO maiúsculo
├─────────────────────────┤
│ Resumen (Portugués)     │
│ Resumen (Inglés)        │
│ Resumen (Alemán)        │  ← Traduzido! ✓
│ Resumen (Francés)       │  ← Traduzido! ✓
└─────────────────────────┘

Quais são tickets relevantes?

Ticket principal:

Tickets relacionados:

Issues relacionadas no vídeo de demonstração:

Artigos de exemplo mencionados no ticket:

  • Artigo em alemão: "Studierendenaustausch Zur Sprachenpolitik..."
  • Artigo em russo: "Бахтин почти мой товарищ..."
  • Artigo em francês: "Analyse de la diversite humaine..."

AI Assisted

- Adiciona dicionário LANGUAGE_TRANSLATIONS com 40+ idiomas em
choices.py
- Adiciona função get_language_name() para traduzir códigos ISO
- Adiciona função get_language_code_upper() para códigos ISO maiúsculos
- Adiciona função register_language_filters() para registrar filtros
Jinja2
- Usa g.interface_language (compatível com PR scieloorg#366)
- Suporta traduções de interface em pt/en/es

Corrige: TK-355
- Exibe nomes de idiomas traduzidos nos menus de resumo/texto/PDF
- Mostra códigos ISO em maiúsculo no botão colapsado (DE, FR, RU)
- Mostra nomes traduzidos no dropdown expandido (Alemão, German, Alemán)
- Corrige IDs duplicados em levelMenu_pdf.html (btnGroupDropPDF)
- Usa g.interface_language ao invés de session.get('lang')
- Compatível com abordagem Accept-Language header do PR scieloorg#366

Antes: Resumo (de), Texto (fr), PDF (ru)
Depois: Resumo (Alemão), Texto (Francês), PDF (Russo)

Corrige: TK-355
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements internationalization for language names in article menus (abstract, text, PDF), addressing an issue where languages beyond Portuguese, English, and Spanish appeared as raw ISO codes instead of translated names. The implementation introduces a centralized translation dictionary with 40+ languages and Jinja2 filters for automatic translation based on the interface language.

Changes:

  • Added LANGUAGE_TRANSLATIONS dictionary in choices.py with translations for 40+ languages across pt/en/es interfaces
  • Created utility functions (get_language_name, get_language_code_upper, register_language_filters) in utils.py for language name resolution
  • Updated templates (levelMenu_abstracts.html, levelMenu_texts.html, levelMenu_pdf.html) to use new translation filters
  • Fixed duplicate HTML IDs in PDF menu (btnGroupDropPDFSingle vs btnGroupDropPDFMultiple)

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
opac/webapp/choices.py Adds LANGUAGE_TRANSLATIONS dictionary with 40+ languages, each with translations to pt/en/es
opac/webapp/utils/utils.py Implements language translation utility functions and Jinja2 filter registration
opac/webapp/templates/article/includes/levelMenu_abstracts.html Replaces hardcoded language name conditionals with dynamic filter-based translation
opac/webapp/templates/article/includes/levelMenu_texts.html Replaces hardcoded language name conditionals with dynamic filter-based translation
opac/webapp/templates/article/includes/levelMenu_pdf.html Replaces hardcoded language name conditionals with dynamic filter-based translation; fixes duplicate ID issue

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

{# Dropdown expandido: mostra nome traduzido do idioma #}
{# g.interface_language contém o idioma da interface (pt/en/es) #}
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
({{ abstract['language']|language_name(g.interface_language) }})
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable g.interface_language is used but does not appear to be set anywhere in the codebase. The current implementation uses session['lang'] (as seen in webapp/main/views.py in the get_locale() function). Until PR #370 is merged and g.interface_language is properly set, this code will fail with an AttributeError. Consider using a fallback approach that works with the current codebase, such as using session.get('lang', 'en') or calling get_locale() directly.

Copilot uses AI. Check for mistakes.
({{ abstract['language'] }})
{% endif %}
{# Dropdown expandido: mostra nome traduzido do idioma #}
({{ abstract['language']|language_name(g.interface_language) }})
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable g.interface_language is used but does not appear to be set anywhere in the codebase. The current implementation uses session['lang'] (as seen in webapp/main/views.py in the get_locale() function). Until PR #370 is merged and g.interface_language is properly set, this code will fail with an AttributeError. Consider using a fallback approach that works with the current codebase, such as using session.get('lang', 'en') or calling get_locale() directly.

Copilot uses AI. Check for mistakes.
{# Dropdown expandido: mostra nome traduzido do idioma #}
{# g.interface_language contém o idioma da interface (pt/en/es) #}
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
({{ lang|language_name(g.interface_language) }})
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable g.interface_language is used but does not appear to be set anywhere in the codebase. The current implementation uses session['lang'] (as seen in webapp/main/views.py in the get_locale() function). Until PR #370 is merged and g.interface_language is properly set, this code will fail with an AttributeError. Consider using a fallback approach that works with the current codebase, such as using session.get('lang', 'en') or calling get_locale() directly.

Copilot uses AI. Check for mistakes.
{# Dropdown: mostra "Download PDF" com nome traduzido do idioma #}
{# g.interface_language contém o idioma da interface (pt/en/es) #}
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
{% trans %}Download PDF{% endtrans %} ({{ pdf.lang|language_name(g.interface_language) }})
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable g.interface_language is used but does not appear to be set anywhere in the codebase. The current implementation uses session['lang'] (as seen in webapp/main/views.py in the get_locale() function). Until PR #370 is merged and g.interface_language is properly set, this code will fail with an AttributeError. Consider using a fallback approach that works with the current codebase, such as using session.get('lang', 'en') or calling get_locale() directly.

Copilot uses AI. Check for mistakes.
{{ pdf.lang }}
{% endif %}
{# Dropdown: mostra "Download PDF" com nome traduzido do idioma #}
{% trans %}Download PDF{% endtrans %} ({{ pdf.lang|language_name(g.interface_language) }})
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable g.interface_language is used but does not appear to be set anywhere in the codebase. The current implementation uses session['lang'] (as seen in webapp/main/views.py in the get_locale() function). Until PR #370 is merged and g.interface_language is properly set, this code will fail with an AttributeError. Consider using a fallback approach that works with the current codebase, such as using session.get('lang', 'en') or calling get_locale() directly.

Copilot uses AI. Check for mistakes.

# Também disponibiliza como função global nos templates
app.jinja_env.globals['get_language_name'] = get_language_name
app.jinja_env.globals['get_language_code_upper'] = get_language_code_upper
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function register_language_filters() is defined but never called. The Jinja2 filters language_name and language_code_upper need to be registered during application initialization (e.g., in create_app() function in webapp/__init__.py) for them to be available in templates. Without calling this function, the templates will fail with an "UndefinedError: No filter named 'language_name'" error.

Suggested change
app.jinja_env.globals['get_language_code_upper'] = get_language_code_upper
app.jinja_env.globals['get_language_code_upper'] = get_language_code_upper
# Registra automaticamente os filtros se existir uma instância global de app
if hasattr(webapp, 'app'):
register_language_filters(webapp.app)

Copilot uses AI. Check for mistakes.
Comment on lines +800 to +876
def get_language_name(lang_code, interface_lang='en'):
"""
Retorna o nome do idioma traduzido de acordo com o idioma da interface.

Args:
lang_code (str): Código ISO 639-1 do idioma (ex: 'de', 'fr', 'ru')
interface_lang (str): Idioma da interface ('pt', 'en' ou 'es')

Returns:
str: Nome do idioma traduzido ou código ISO em maiúsculo se não encontrado

Exemplos:
>>> get_language_name('de', 'pt')
'Alemão'
>>> get_language_name('de', 'en')
'German'
>>> get_language_name('fr', 'es')
'Francés'
>>> get_language_name('xx', 'pt')
'XX'
"""

if not lang_code:
return ''

lang_code = lang_code.lower()
interface_lang = interface_lang.lower()

# Se o código não está no dicionário, retorna em maiúsculo
if lang_code not in LANGUAGE_TRANSLATIONS:
return lang_code.upper()

# Se o idioma da interface não está disponível, usa inglês como fallback
if interface_lang not in LANGUAGE_TRANSLATIONS[lang_code]:
interface_lang = 'en'

# Retorna a tradução (lazy_gettext precisa ser convertido para string)
translation = LANGUAGE_TRANSLATIONS[lang_code].get(interface_lang, lang_code.upper())
return str(translation)


def get_language_code_upper(lang_code):
"""
Retorna o código ISO do idioma em maiúsculo.

Args:
lang_code (str): Código ISO 639-1 do idioma

Returns:
str: Código em maiúsculo (ex: 'DE', 'FR', 'RU')

Exemplos:
>>> get_language_code_upper('de')
'DE'
>>> get_language_code_upper('fr')
'FR'
"""
return lang_code.upper() if lang_code else ''


def register_language_filters(app):
"""
Registra os filtros Jinja2 para tradução de idiomas.

Args:
app: Instância do Flask app

Uso nos templates:
{{ 'de'|language_name('pt') }} -> 'Alemão'
{{ 'de'|language_code_upper }} -> 'DE'
"""
app.jinja_env.filters['language_name'] = get_language_name
app.jinja_env.filters['language_code_upper'] = get_language_code_upper

# Também disponibiliza como função global nos templates
app.jinja_env.globals['get_language_name'] = get_language_name
app.jinja_env.globals['get_language_code_upper'] = get_language_code_upper
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new utility functions get_language_name(), get_language_code_upper(), and register_language_filters() lack test coverage. The repository has comprehensive test coverage for utils (see test_utils.py), and these new functions should have unit tests to verify: 1) correct translation for supported languages, 2) fallback behavior for unsupported languages, 3) handling of None/empty input, 4) case-insensitive language code handling, and 5) filter registration functionality.

Copilot uses AI. Check for mistakes.
{% endif %}
{# Dropdown expandido: mostra nome traduzido do idioma #}
{# g.interface_language contém o idioma da interface (pt/en/es) #}
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment references "PR #366" but the PR description consistently mentions "PR #370" as the related PR for migrating from session.get('lang') to g.interface_language. This inconsistency could cause confusion for future maintainers. Please verify and correct the PR number in the comment.

Suggested change
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
{# Compatível com PR #370 - migração de session.get('lang') para g.interface_language #}

Copilot uses AI. Check for mistakes.
{% endif %}
{# Dropdown: mostra "Download PDF" com nome traduzido do idioma #}
{# g.interface_language contém o idioma da interface (pt/en/es) #}
{# Compatível com PR #366 - migração de session.get('lang') para g.interface_language #}
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment references "PR #366" but the PR description consistently mentions "PR #370" as the related PR for migrating from session.get('lang') to g.interface_language. This inconsistency could cause confusion for future maintainers. Please verify and correct the PR number in the comment.

Copilot uses AI. Check for mistakes.
Comment on lines +231 to +236
'al': { # Alias (compatibilidade com ISO3166_ALPHA2 existente)
'pt': __('Albanês'),
'en': __('Albanian'),
'es': __('Albanés')
},
'sq': { # Código ISO correto para albanês
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indicates 'al' is an "Alias (compatibilidade com ISO3166_ALPHA2 existente)", but this is misleading. 'al' is an ISO 3166 country code (Albania), not an ISO 639 language code. ISO 639-1 uses 'sq' for Albanian language. While keeping 'al' for backward compatibility may be necessary, the comment should clarify that 'al' is not a valid ISO 639 language code and exists only for legacy support.

Suggested change
'al': { # Alias (compatibilidade com ISO3166_ALPHA2 existente)
'pt': __('Albanês'),
'en': __('Albanian'),
'es': __('Albanés')
},
'sq': { # Código ISO correto para albanês
'al': { # Alias legado para compatibilidade; 'al' é código ISO 3166 (Albânia), não ISO 639-1. Use 'sq' para albanês.
'pt': __('Albanês'),
'en': __('Albanian'),
'es': __('Albanés')
},
'sq': { # Código ISO 639-1 correto para albanês

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +231 to +235
'al': { # Alias (compatibilidade com ISO3166_ALPHA2 existente)
'pt': __('Albanês'),
'en': __('Albanian'),
'es': __('Albanés')
},
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code 'al' is an ISO 3166-1 country code for Albania, not an ISO 639-1 language code. The correct language code for Albanian is 'sq', which is already defined below. While this may be added for backward compatibility as the comment indicates, having both could cause confusion. Consider documenting why 'al' is needed or removing it if it's not actively used in the database.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano acho que a abordagem deste dicionário não é sustentável, além disso no lugar de idioma está sendo usado país. Use a lista iso de idiomas. Crie um dicionário simples de chave e valor sendo a chave o código do idioma e o valor o nome do idioma no idioma original ou em inglês dentro da marca {% trans %}{{ lang_name }}{% endtrans %}

Comment on lines +22 to 23
({{ abstract['language']|language_name(g.interface_language) }})
</a>
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The templates reference g.interface_language, but this variable is not defined anywhere in the current codebase. The templates will fail with an AttributeError when trying to access this undefined attribute.

If this PR depends on PR #370 (or #366 as mentioned in comments) that introduces g.interface_language, that dependency needs to be clearly stated and this PR should not be merged until the dependent PR is merged first. Alternatively, you need to add a fallback that uses the current session.get('lang') approach until the migration is complete.

Copilot uses AI. Check for mistakes.
if not lang_code:
return ''

lang_code = lang_code.lower()
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function should handle the case where interface_lang is None more explicitly. While line 826 does .lower() on it, if interface_lang is None, this will raise an AttributeError. Consider adding a check: if not interface_lang: interface_lang = 'en' before line 826.

Suggested change
lang_code = lang_code.lower()
lang_code = lang_code.lower()
if not interface_lang:
interface_lang = 'en'

Copilot uses AI. Check for mistakes.
Comment on lines +837 to +838
translation = LANGUAGE_TRANSLATIONS[lang_code].get(interface_lang, lang_code.upper())
return str(translation)
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The language_name filter is being called inside loops that iterate over abstracts/texts/PDFs. Each call converts the lazy_gettext result to a string (line 838 in utils.py). While this is unlikely to cause performance issues with a small number of items, consider that the lazy_gettext objects could be evaluated multiple times for the same language code. This is acceptable for the current use case but worth noting if the pattern is extended to larger datasets.

Copilot uses AI. Check for mistakes.
Comment on lines +832 to +837
# Se o idioma da interface não está disponível, usa inglês como fallback
if interface_lang not in LANGUAGE_TRANSLATIONS[lang_code]:
interface_lang = 'en'

# Retorna a tradução (lazy_gettext precisa ser convertido para string)
translation = LANGUAGE_TRANSLATIONS[lang_code].get(interface_lang, lang_code.upper())
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a potential inconsistency in how language codes are handled. The function assumes all entries in LANGUAGE_TRANSLATIONS have all three interface languages (pt, en, es), but if a language entry is missing one of these keys, the code falls back to English (line 834) and then uses .get() with a fallback (line 837). This double fallback is redundant. Once interface_lang is set to 'en' on line 834, the .get() on line 837 will always succeed (assuming 'en' key exists in all language entries). Consider either simplifying this logic or adding validation that all language entries have all three interface languages.

Suggested change
# Se o idioma da interface não está disponível, usa inglês como fallback
if interface_lang not in LANGUAGE_TRANSLATIONS[lang_code]:
interface_lang = 'en'
# Retorna a tradução (lazy_gettext precisa ser convertido para string)
translation = LANGUAGE_TRANSLATIONS[lang_code].get(interface_lang, lang_code.upper())
lang_translations = LANGUAGE_TRANSLATIONS[lang_code]
# Se o idioma da interface não está disponível, usa inglês como fallback (se existir)
if interface_lang not in lang_translations and 'en' in lang_translations:
interface_lang = 'en'
# Retorna a tradução (lazy_gettext precisa ser convertido para string)
translation = lang_translations.get(interface_lang, lang_code.upper())

Copilot uses AI. Check for mistakes.
Copy link
Member

@robertatakenaka robertatakenaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano Realizar as correções

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants