feat: internationalization with EN, ES, PT-BR - #1
Open
eanorambuena wants to merge 16 commits into
Open
Conversation
There was a problem hiding this comment.
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/i18nconfiguration and introduced locale dictionaries (en,es,pt) underi18n/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.
| 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')) }, |
| 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')) }, |
| <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> |
| 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')) }, |
| @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 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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds full internationalization support with 3 locales:
/)/es/)/pt/)Changes
@nuxtjs/i18n@10.4.0i18n/locales/withen.ts,es.ts,pt.ts$t()useHead()withcomputed(() => t('key'))prefix_except_default— English no prefix, others get/es/,/pt/localePath()to preserve locale across navigationTesting
Notes
feat/i18nbranch