feat(i18n): add Portuguese (Brazil) locale (pt-BR) (#6943)

Finalmente o idioma em Portugues do Brasil verá a luz do dia (se tudo
correr bem).

What has been done:

- Added pt-BR to .i18nrc.cjs and settings
- Included loaders in src/i18n.ts and apps/desktop-ui/src/i18n.ts
- Now Portuguese (BR) is displayed in the language selector
- Created empty main.json, commands.json, settings.json and
nodeDefs.json files to be populated by CI

- Checklist: the language appears in the dropdown list, selection occurs
without errors, the fallback to English, in case technical terms have no
translation, is working correctly.

- I will maintain the pt-br translation and review for as long as
necessary.

---------

Co-authored-by: Comfy Contributor <dev@example.com>
This commit is contained in:
JonatanAtila
2025-11-27 19:46:27 -03:00
committed by GitHub
parent 923695ffde
commit e248ecfa4e
10 changed files with 27 additions and 12 deletions

View File

@@ -9,7 +9,7 @@ module.exports = defineConfig({
entry: 'src/locales/en', entry: 'src/locales/en',
entryLocale: 'en', entryLocale: 'en',
output: 'src/locales', output: 'src/locales',
outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar', 'tr'], outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar', 'tr', 'pt-BR'],
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream. reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream.
'latent' is the short form of 'latent space'. 'latent' is the short form of 'latent space'.
'mask' is in the context of image processing. 'mask' is in the context of image processing.

View File

@@ -54,6 +54,7 @@
# Translations # Translations
/src/locales/ @Yorha4D @KarryCharon @shinshin86 @Comfy-Org/comfy_maintainer @Comfy-org/comfy_frontend_devs /src/locales/ @Yorha4D @KarryCharon @shinshin86 @Comfy-Org/comfy_maintainer @Comfy-org/comfy_frontend_devs
/src/locales/pt-BR/ @JonatanAtila @Yorha4D @KarryCharon @shinshin86
# LLM Instructions (blank on purpose) # LLM Instructions (blank on purpose)
.claude/ .claude/

View File

@@ -59,7 +59,8 @@ const LOCALES = [
['fr', 'Français'], ['fr', 'Français'],
['es', 'Español'], ['es', 'Español'],
['ar', 'عربي'], ['ar', 'عربي'],
['tr', 'Türkçe'] ['tr', 'Türkçe'],
['pt-BR', 'Português (BR)']
] as const satisfies ReadonlyArray<[string, string]> ] as const satisfies ReadonlyArray<[string, string]>
type SupportedLocale = (typeof LOCALES)[number][0] type SupportedLocale = (typeof LOCALES)[number][0]

View File

@@ -40,7 +40,8 @@ const localeLoaders: Record<
ru: () => import('@frontend-locales/ru/main.json'), ru: () => import('@frontend-locales/ru/main.json'),
tr: () => import('@frontend-locales/tr/main.json'), tr: () => import('@frontend-locales/tr/main.json'),
zh: () => import('@frontend-locales/zh/main.json'), zh: () => import('@frontend-locales/zh/main.json'),
'zh-TW': () => import('@frontend-locales/zh-TW/main.json') 'zh-TW': () => import('@frontend-locales/zh-TW/main.json'),
'pt-BR': () => import('@frontend-locales/pt-BR/main.json')
} }
const nodeDefsLoaders: Record< const nodeDefsLoaders: Record<
@@ -55,7 +56,8 @@ const nodeDefsLoaders: Record<
ru: () => import('@frontend-locales/ru/nodeDefs.json'), ru: () => import('@frontend-locales/ru/nodeDefs.json'),
tr: () => import('@frontend-locales/tr/nodeDefs.json'), tr: () => import('@frontend-locales/tr/nodeDefs.json'),
zh: () => import('@frontend-locales/zh/nodeDefs.json'), zh: () => import('@frontend-locales/zh/nodeDefs.json'),
'zh-TW': () => import('@frontend-locales/zh-TW/nodeDefs.json') 'zh-TW': () => import('@frontend-locales/zh-TW/nodeDefs.json'),
'pt-BR': () => import('@frontend-locales/pt-BR/nodeDefs.json')
} }
const commandsLoaders: Record< const commandsLoaders: Record<
@@ -70,7 +72,8 @@ const commandsLoaders: Record<
ru: () => import('@frontend-locales/ru/commands.json'), ru: () => import('@frontend-locales/ru/commands.json'),
tr: () => import('@frontend-locales/tr/commands.json'), tr: () => import('@frontend-locales/tr/commands.json'),
zh: () => import('@frontend-locales/zh/commands.json'), zh: () => import('@frontend-locales/zh/commands.json'),
'zh-TW': () => import('@frontend-locales/zh-TW/commands.json') 'zh-TW': () => import('@frontend-locales/zh-TW/commands.json'),
'pt-BR': () => import('@frontend-locales/pt-BR/commands.json')
} }
const settingsLoaders: Record< const settingsLoaders: Record<
@@ -85,7 +88,8 @@ const settingsLoaders: Record<
ru: () => import('@frontend-locales/ru/settings.json'), ru: () => import('@frontend-locales/ru/settings.json'),
tr: () => import('@frontend-locales/tr/settings.json'), tr: () => import('@frontend-locales/tr/settings.json'),
zh: () => import('@frontend-locales/zh/settings.json'), zh: () => import('@frontend-locales/zh/settings.json'),
'zh-TW': () => import('@frontend-locales/zh-TW/settings.json') 'zh-TW': () => import('@frontend-locales/zh-TW/settings.json'),
'pt-BR': () => import('@frontend-locales/pt-BR/settings.json')
} }
// Track which locales have been loaded // Track which locales have been loaded

View File

@@ -36,7 +36,8 @@ const localeLoaders: Record<
ru: () => import('./locales/ru/main.json'), ru: () => import('./locales/ru/main.json'),
tr: () => import('./locales/tr/main.json'), tr: () => import('./locales/tr/main.json'),
zh: () => import('./locales/zh/main.json'), zh: () => import('./locales/zh/main.json'),
'zh-TW': () => import('./locales/zh-TW/main.json') 'zh-TW': () => import('./locales/zh-TW/main.json'),
'pt-BR': () => import('./locales/pt-BR/main.json')
} }
const nodeDefsLoaders: Record< const nodeDefsLoaders: Record<
@@ -51,7 +52,8 @@ const nodeDefsLoaders: Record<
ru: () => import('./locales/ru/nodeDefs.json'), ru: () => import('./locales/ru/nodeDefs.json'),
tr: () => import('./locales/tr/nodeDefs.json'), tr: () => import('./locales/tr/nodeDefs.json'),
zh: () => import('./locales/zh/nodeDefs.json'), zh: () => import('./locales/zh/nodeDefs.json'),
'zh-TW': () => import('./locales/zh-TW/nodeDefs.json') 'zh-TW': () => import('./locales/zh-TW/nodeDefs.json'),
'pt-BR': () => import('./locales/pt-BR/nodeDefs.json')
} }
const commandsLoaders: Record< const commandsLoaders: Record<
@@ -66,7 +68,8 @@ const commandsLoaders: Record<
ru: () => import('./locales/ru/commands.json'), ru: () => import('./locales/ru/commands.json'),
tr: () => import('./locales/tr/commands.json'), tr: () => import('./locales/tr/commands.json'),
zh: () => import('./locales/zh/commands.json'), zh: () => import('./locales/zh/commands.json'),
'zh-TW': () => import('./locales/zh-TW/commands.json') 'zh-TW': () => import('./locales/zh-TW/commands.json'),
'pt-BR': () => import('./locales/pt-BR/commands.json')
} }
const settingsLoaders: Record< const settingsLoaders: Record<
@@ -81,7 +84,8 @@ const settingsLoaders: Record<
ru: () => import('./locales/ru/settings.json'), ru: () => import('./locales/ru/settings.json'),
tr: () => import('./locales/tr/settings.json'), tr: () => import('./locales/tr/settings.json'),
zh: () => import('./locales/zh/settings.json'), zh: () => import('./locales/zh/settings.json'),
'zh-TW': () => import('./locales/zh-TW/settings.json') 'zh-TW': () => import('./locales/zh-TW/settings.json'),
'pt-BR': () => import('./locales/pt-BR/settings.json')
} }
// Track which locales have been loaded // Track which locales have been loaded

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -416,7 +416,8 @@ export const CORE_SETTINGS: SettingParams[] = [
{ value: 'fr', text: 'Français' }, { value: 'fr', text: 'Français' },
{ value: 'es', text: 'Español' }, { value: 'es', text: 'Español' },
{ value: 'ar', text: 'عربي' }, { value: 'ar', text: 'عربي' },
{ value: 'tr', text: 'Türkçe' } { value: 'tr', text: 'Türkçe' },
{ value: 'pt-BR', text: 'Português (BR)' }
], ],
defaultValue: () => navigator.language.split('-')[0] || 'en' defaultValue: () => navigator.language.split('-')[0] || 'en'
}, },