Skip to content

feat: internationalization with EN, ES, PT-BR - #1

Open
eanorambuena wants to merge 16 commits into
mainfrom
feat/i18n
Open

feat: internationalization with EN, ES, PT-BR#1
eanorambuena wants to merge 16 commits into
mainfrom
feat/i18n

Conversation

@eanorambuena

Copy link
Copy Markdown
Owner

What

Adds full internationalization support with 3 locales:

  • EN — English (default, at root /)
  • ES — Español (at /es/)
  • PT — Português brasileiro (at /pt/)

Changes

  • Installed @nuxtjs/i18n@10.4.0
  • Created i18n/locales/ with en.ts, es.ts, pt.ts
  • Migrated all 36 Vue components/pages from hardcoded strings to $t()
  • Added language selector (EN/ES/PT) in desktop header and mobile menu
  • SEO meta tags use useHead() with computed(() => t('key'))
  • Strategy: prefix_except_default — English no prefix, others get /es/, /pt/
  • Browser language detection with cookie persistence
  • Nav links use localePath() to preserve locale across navigation

Testing

Notes

  • Production (main) was never modified during development
  • All work done exclusively on feat/i18n branch
  • Previous Spanish hardcoded strings in PipelineAI fixed

Copilot AI left a comment

Copy link
Copy Markdown

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 introduces full internationalization (i18n) across the Nuxt app with English (default), Spanish, and Brazilian Portuguese locales, migrating previously hardcoded UI strings to translation keys and adding locale-aware navigation and metadata.

Changes:

  • Added @nuxtjs/i18n configuration and introduced locale dictionaries (en, es, pt) under i18n/locales/.
  • Replaced hardcoded strings across pages/components with $t(...) / t(...), including ARIA labels and toast messaging.
  • Added a language selector to the header (desktop + mobile) and updated various page useHead() fields to be translation-driven.

Reviewed changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
pages/terms.vue Terms page content moved to i18n + dynamic sections rendering + head tags updated
pages/terminal/stock/[symbol].vue Stock detail loading/error/labels converted to i18n
pages/terminal/screener.vue Screener presets/filters/head metadata translated
pages/terminal/pricing.vue Pricing page strings + payment methods/features moved to i18n
pages/terminal/portfolio.vue Portfolio page head/heading translated
pages/terminal/pipeline.vue Pipeline page head + loading fallback translated
pages/terminal/index.vue Terminal index head metadata translated
pages/terminal/alerts.vue Alerts page head/heading/status translated
pages/privacy.vue Privacy policy strings moved to i18n; cookie/services lists rendered from locale data
pages/index.vue Landing page hero/features/head metadata translated
pages/disclaimer.vue Disclaimer page content moved to i18n + dynamic sections rendering + head tags updated
pages/contact.vue Contact page strings + head metadata translated
pages/blog/what-is-a-financial-terminal.vue Blog post migrated to i18n-driven content/sections
pages/blog/understanding-market-indicators.vue Blog post migrated to i18n-driven content/tables/steps
pages/blog/index.vue Blog index header + post metadata sourced from i18n
pages/blog/build-diversified-portfolio.vue Blog post partially migrated to i18n-driven sections + head metadata
pages/about.vue About page strings moved to i18n; features list sourced from locale data
package.json Added @nuxtjs/i18n dependency
nuxt.config.ts Registered @nuxtjs/i18n module and configured locales/strategy/detection
i18n/locales/en.ts Added English locale dictionary
i18n/locales/es.ts Added Spanish locale dictionary
i18n/locales/pt.ts Added PT-BR locale dictionary
error.vue Error page fallback strings localized
composables/useAIPipeline.ts Replaced Spanish validation error with English text
components/Toast.vue Localized dismiss button ARIA label
components/SearchBar.vue Localized placeholder + ARIA labels + empty/searching messages
components/PortfolioTable.vue Localized labels/placeholders/toasts/empty states
components/pipeline/PipelineAI.vue Localized UI chrome + placeholders/results summary
components/NewsFeed.vue Localized headings/empty state + localized relative-time strings
components/MarketOverview.vue Localized headings/loading/empty states + ARIA labels
components/MarketCategoryTable.vue Localized table headers/loading labels/placeholders + ARIA labels
components/KalmanAnalysis.vue Localized headings/labels/signal text
components/Header.vue Added locale switcher; nav labels localized; locale-aware links via localePath()
components/ChileIndicators.vue Localized headings/loading/empty states + ARIA labels
components/AppFooter.vue Localized footer labels + modal copy
components/AlertForm.vue Localized labels/placeholders/toasts/button text
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

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

Comment thread pages/terms.vue Outdated
Comment thread pages/terms.vue
title: computed(() => t('staticPages.terms.title')),
meta: [
{ name: 'description', content: 'Kalmate Terms of Service governing the use of the free open-source financial terminal, data pipeline, and portfolio tracking tools.' },
{ name: 'description', content: computed(() => t('staticPages.terms.updated')) },
Comment thread pages/privacy.vue
title: computed(() => t('staticPages.privacy.title')),
meta: [
{ name: 'description', content: 'Kalmate Privacy Policy. Learn how we handle cookies, Google AdSense data, local storage, and third-party services on our financial terminal.' },
{ name: 'description', content: computed(() => t('staticPages.privacy.updated')) },
Comment thread pages/disclaimer.vue Outdated
<a href="mailto:a25.eanorambuena@gmail.com" class="text-[#00c853] hover:underline">a25.eanorambuena@gmail.com</a>
<p v-if="section.text && !section.text1" class="text-[#ccc] leading-relaxed">
{{ section.text }}
<a v-if="section.title === 'Contact'" href="mailto:a25.eanorambuena@gmail.com" class="text-[#00c853] hover:underline">a25.eanorambuena@gmail.com</a>
Comment thread pages/disclaimer.vue
title: computed(() => t('staticPages.disclaimer.title')),
meta: [
{ name: 'description', content: 'Kalmate disclaimer. Market data is for informational purposes only and does not constitute financial advice. No guarantee of data accuracy.' },
{ name: 'description', content: computed(() => t('staticPages.disclaimer.updated')) },
Comment thread components/Header.vue
@click="setLocale(l.code)"
class="text-[11px] font-mono font-bold px-1.5 py-0.5 rounded transition-colors"
:class="locale === l.code ? 'bg-[#00c853] text-black' : 'text-[#666] hover:text-[#ccc]'"
:aria-label="l.code === 'en' ? 'English' : 'Español'"
Comment on lines +15 to +16
{{ $t('pipeline.ai.placeholder') }}<br>
{{ $t('pipeline.ai.examplePrefix') }}<span class="text-[#888] font-mono">chart AAPL con SMA20</span>
Comment thread components/AppFooter.vue
Comment on lines +16 to +21
<h4 class="text-white text-xs font-bold tracking-widest uppercase mb-4">{{ $t('footer.links') }}</h4>
<ul class="space-y-2.5">
<li><NuxtLink to="/terminal" class="text-[#888] text-sm hover:text-white transition-colors">Terminal</NuxtLink></li>
<li><NuxtLink to="/about" class="text-[#888] text-sm hover:text-white transition-colors">About</NuxtLink></li>
<li><NuxtLink to="/contact" class="text-[#888] text-sm hover:text-white transition-colors">Contact</NuxtLink></li>
<li><NuxtLink to="/blog" class="text-[#888] text-sm hover:text-white transition-colors">Blog</NuxtLink></li>
<li><NuxtLink to="/terminal" class="text-[#888] text-sm hover:text-white transition-colors">{{ $t('footer.terminal') }}</NuxtLink></li>
<li><NuxtLink to="/about" class="text-[#888] text-sm hover:text-white transition-colors">{{ $t('footer.about') }}</NuxtLink></li>
<li><NuxtLink to="/contact" class="text-[#888] text-sm hover:text-white transition-colors">{{ $t('footer.contact') }}</NuxtLink></li>
<li><NuxtLink to="/blog" class="text-[#888] text-sm hover:text-white transition-colors">{{ $t('footer.blog') }}</NuxtLink></li>
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.

2 participants