Conversation
Implement 2FA enforcement UI when users don't have 2FA enabled but their organization requires it. Shows a fail card similar to password policy enforcement with a "Setup 2FA Now" button that auto-triggers the 2FA setup flow. Prevents data loading and displays enforcement message across dashboard, apps list, and organization settings pages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds 2FA/password-compliance gating across UI and store: localized strings added; pages/components (FailedCard, Banner, app, dashboard, settings layout) detect redacted security access and block or reroute flows; account settings auto-opens MFA setup via query; org store avoids false failure states and swallows dashboard update errors. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as Component/Page
participant Store as Org Store
participant Router as Router (Account Settings)
User->>UI: Request page (dashboard/app/settings)
UI->>Store: Read org security flags (enforcing_2fa, 2fa_has_access, password_policy_config, password_has_access)
Store-->>UI: Return org state
UI->>UI: Compute lacksSecurityAccess
alt Security access denied (redacted)
UI->>UI: Render FailedCard with 2FA/password prompts
User->>UI: Click "Setup 2FA Now"
UI->>Router: Navigate to account settings with ?setup2fa=true
Router->>Router: onMounted sees setup2fa, clears query
Router->>UI: Call handleMfa() → open MFA setup dialog
else Security access granted
UI->>Store: Fetch apps/dashboard data
Store-->>UI: Return data
UI->>User: Render normal content
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/components/Banner.vue (1)
49-55: Same duplication issue as dashboard.vue.This
lacksSecurityAccesscomputed is identical to the one insrc/pages/dashboard.vue(lines 22-28) andsrc/pages/app/index.vue(lines 28-34). Please see the refactoring suggestion in the dashboard.vue review comment to centralize this logic in the organization store.src/pages/app/index.vue (1)
28-34: Same duplication issue as dashboard.vue and Banner.vue.This is the third instance of identical
lacksSecurityAccesslogic. Please see the refactoring suggestion in the dashboard.vue review comment to centralize this in the organization store.
🧹 Nitpick comments (2)
src/pages/dashboard.vue (1)
22-28: Refactor duplicated security access logic to organization store.The
lacksSecurityAccesscomputed is duplicated identically insrc/pages/app/index.vue(lines 28-34) andsrc/components/Banner.vue(lines 49-55). This violates the DRY principle and increases maintenance burden.🔎 Recommended refactor: Add getter to organization store
In
src/stores/organization.ts, add a getter:+ // Check if user lacks security compliance (2FA or password) + get lacksSecurityAccess(): boolean { + const org = this.currentOrganization + const lacks2FA = org?.enforcing_2fa === true && org?.['2fa_has_access'] === false + const lacksPassword = org?.password_policy_config?.enabled && org?.password_has_access === false + return lacks2FA || lacksPassword + }Then replace local computed properties in dashboard.vue, app/index.vue, and Banner.vue:
-const lacksSecurityAccess = computed(() => { - const org = organizationStore.currentOrganization - const lacks2FA = org?.enforcing_2fa === true && org?.['2fa_has_access'] === false - const lacksPassword = org?.password_policy_config?.enabled && org?.password_has_access === false - return lacks2FA || lacksPassword -}) +const lacksSecurityAccess = computed(() => organizationStore.lacksSecurityAccess)src/stores/organization.ts (1)
287-295: Consider extracting duplicate security-check logic into a helper.This logic duplicates lines 86-94 in the watch handler. Extracting it into a reusable function would improve maintainability and reduce the risk of divergence.
🔎 Proposed refactor
+function shouldMarkOrgAsFailed(org: Organization | undefined): boolean { + if (!org) return false + const lacks2FAAccess = org.enforcing_2fa === true && org['2fa_has_access'] === false + const lacksPasswordAccess = org.password_policy_config?.enabled && org.password_has_access === false + if (lacks2FAAccess || lacksPasswordAccess) { + return false + } + return !(!!org.paying || (org.trial_left ?? 0) > 0) +}Then use
currentOrganizationFailed.value = shouldMarkOrgAsFailed(currentOrganizationRaw)in both locations.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
messages/en.jsonsrc/components/Banner.vuesrc/components/FailedCard.vuesrc/layouts/settings.vuesrc/pages/app/index.vuesrc/pages/dashboard.vuesrc/pages/settings/account/index.vuesrc/stores/organization.ts
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.vue: Use Vue 3 with Composition API and<script setup>syntax for frontend components
Style components using TailwindCSS with DaisyUI components
src/**/*.vue: Use Vue 3<script setup>syntax exclusively for all Vue component scripts
Use Tailwind utility classes for layout and spacing in Vue components
Use DaisyUI components (d-btn,d-input,d-card) for interactive elements in Vue components
Use Konsta components ONLY for safe area helpers (top/bottom insets) in Vue components; avoid other uses
UseuseRoute()fromvue-routerto access route parameters anduseRouter()for programmatic navigation in Vue componentsUse DaisyUI (
d-prefixed classes) for buttons, inputs, and other interactive primitives to keep behavior and spacing consistent
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use single quotes and no semicolons per @antfu/eslint-config
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/stores/organization.tssrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/pages/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
Use file-based routing with unplugin-vue-router for frontend pages
Frontend file-based routing uses
src/pages/directory structure; routes auto-generate withunplugin-vue-routerand types are available insrc/typed-router.d.ts
Files:
src/pages/dashboard.vuesrc/pages/settings/account/index.vuesrc/pages/app/index.vue
{capacitor.config.{ts,js},src/**/*.{ts,tsx,vue}}
📄 CodeRabbit inference engine (CLAUDE.md)
Mobile apps should use Capacitor with app ID
ee.forgr.capacitor_gofor native mobile functionality
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/stores/organization.tssrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/**/*.{ts,tsx,vue,js}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
~/alias for imports fromsrc/directory in frontend TypeScript and Vue components
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/stores/organization.tssrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Frontend ESLint must pass before commit; run
bun lint:fixto auto-fix issues in frontend files
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/stores/organization.tssrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/**/*.{vue,css,scss}
📄 CodeRabbit inference engine (AGENTS.md)
The web client is built with Vue.js and Tailwind CSS; lean on utility classes and composition-friendly patterns rather than bespoke CSS
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/**/*.{vue,ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Konsta components are reserved for the safe area helpers; avoid importing
konstaanywhere else in the app
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/stores/organization.tssrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/**/*.{css,scss,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Mirror the Capgo design palette from
src/styles/style.css(e.g.,--color-primary-500: #515271,--color-azure-500: #119eff) when introducing new UI, using deep slate bases with the Extract azure highlight and soft radii
Files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
src/layouts/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
Page layout components should be organized in
src/layouts/directory
Files:
src/layouts/settings.vue
src/stores/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Pinia stores for state management
Files:
src/stores/organization.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use TypeScript strict mode with path aliases mapping
~/tosrc/
Files:
src/stores/organization.ts
src/components/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
Reusable Vue components should be organized in
src/components/directory
Files:
src/components/FailedCard.vuesrc/components/Banner.vue
🧠 Learnings (7)
📓 Common learnings
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:19.594Z
Learning: In the 2FA enforcement implementation for supabase/migrations: When an org has enforcing_2fa=true, all users including super_admins must have 2FA enabled before accessing any org functions (including check_org_members_2fa_enabled); this is intentional behavior to ensure consistent security enforcement without exceptions for admins.
📚 Learning: 2025-12-05T17:34:25.556Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T17:34:25.556Z
Learning: Applies to src/stores/**/*.{ts,tsx} : Use Pinia stores for state management
Applied to files:
src/pages/dashboard.vuesrc/pages/app/index.vue
📚 Learning: 2025-12-05T17:34:25.556Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T17:34:25.556Z
Learning: Applies to src/**/*.vue : Use Vue 3 with Composition API and `<script setup>` syntax for frontend components
Applied to files:
src/pages/dashboard.vuesrc/components/FailedCard.vuesrc/pages/app/index.vue
📚 Learning: 2025-12-23T01:19:04.593Z
Learnt from: riderx
Repo: Cap-go/capgo PR: 1297
File: src/components/dashboard/DeploymentBanner.vue:77-79
Timestamp: 2025-12-23T01:19:04.593Z
Learning: In the Cap-go codebase, ensure that app permission checks never include the role 'owner'. App-level permissions should be based on the user_min_right enum with values: read, upload, write, admin, super_admin (and NOT owner). This pattern applies across Vue components that perform permission checks; if you find a check referencing 'owner' for app-level access, replace it with the appropriate user_min_right value and keep organization-level owner handling in organization.ts.
Applied to files:
src/pages/dashboard.vuesrc/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/components/FailedCard.vuesrc/pages/app/index.vuesrc/components/Banner.vue
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to src/**/*.vue : Use `useRoute()` from `vue-router` to access route parameters and `useRouter()` for programmatic navigation in Vue components
Applied to files:
src/layouts/settings.vuesrc/pages/settings/account/index.vuesrc/components/FailedCard.vuesrc/pages/app/index.vue
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to src/**/*.vue : Use Vue 3 `<script setup>` syntax exclusively for all Vue component scripts
Applied to files:
src/pages/app/index.vue
📚 Learning: 2025-12-05T17:34:25.556Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T17:34:25.556Z
Learning: Applies to {capacitor.config.{ts,js},src/**/*.{ts,tsx,vue}} : Mobile apps should use Capacitor with app ID `ee.forgr.capacitor_go` for native mobile functionality
Applied to files:
src/components/Banner.vue
🪛 GitHub Actions: Run tests
src/layouts/settings.vue
[error] 10-10: perfectionist/sort-imports: Expected "/components/FailedCard.vue" to come before "/components/Tabs.vue"
🔇 Additional comments (12)
src/pages/settings/account/index.vue (1)
7-7: LGTM! Well-implemented auto-trigger for 2FA setup.The route-aware MFA auto-setup flow is clean and well-commented. Using
nextTick()after clearing the query parameter is a smart approach to prevent the DialogV2's route watcher from closing the dialog prematurely.Also applies to: 9-9, 28-28, 548-556
src/pages/dashboard.vue (1)
33-37: LGTM! Appropriate security gating for data fetch.The early return prevents unnecessary data fetching when security access is denied, which is the correct behavior per the PR objectives.
src/layouts/settings.vue (1)
22-33: LGTM! Smart security gating that preserves account access.The
shouldBlockContentlogic correctly blocks only organization settings while allowing account settings access, which is essential—users need to access account settings to enable 2FA and resolve the enforcement issue. The comment on Line 30 helpfully explains this design decision.src/components/Banner.vue (1)
70-72: LGTM! Appropriate guard for unreliable data.Preventing the billing banner from displaying when security access is lacking is correct—the organization data may be incomplete or unreliable in this state.
src/pages/app/index.vue (1)
45-50: LGTM! Consistent security gating.The early return matches the pattern in dashboard.vue and correctly prevents data fetching when security access is denied.
messages/en.json (1)
1381-1383: LGTM!The new i18n keys for 2FA enforcement follow the established naming conventions and message patterns (consistent with the password policy keys like
password-policy-requiredandupdate-password-now). The messages are clear and user-friendly.src/components/FailedCard.vue (4)
1-11: LGTM!Imports are appropriate and follow the coding guidelines. Using
useRoute()from vue-router for route awareness andvue-sonnerfor toast notifications aligns with project patterns.
19-28: LGTM!The computed properties correctly implement the security access priority chain (password policy → 2FA → subscription). The bracket notation
org?.['2fa_has_access']is the correct approach for properties starting with a digit.
38-55: LGTM!The
goToAccountSettingsnavigation with query param andcopyOrgIdclipboard function are well-implemented. Good defensive programming with the early return on missingorgId, and proper error handling with user-friendly toast feedback.
93-125: LGTM!The 2FA enforcement card follows the established visual pattern from the password policy card. The shield icon is appropriate for 2FA security messaging, and the
v-else-ifchain correctly prioritizes security policies over subscription status.src/stores/organization.ts (2)
86-94: LGTM!The security access gating logic correctly prevents marking the organization as "failed" when the user lacks 2FA or password access. The comment accurately explains that the data is redacted and unreliable in these states. Based on learnings, this aligns with the intentional 2FA enforcement behavior that applies to all users without exceptions.
112-118: LGTM!Wrapping
updateDashboardin try/catch prevents dashboard fetch failures from blocking the UI flow when users lack security access. Logging the error is appropriate for debugging.
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added new translations for 2FA setup access and requirement messages in German, Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Turkish, Vietnamese, and Chinese. This enhances user experience by providing clear instructions for enabling 2FA across different languages. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (8)
messages/hi.json (1)
134-183: Empty-string translations may cause blank UI instead of fallback textSeveral newly added keys in this area (for example
add-webhook,allow-dev-builds,allow-device,allow-prod-builds, and nearby notification/security keys) are defined with""as the value rather than omitting the key or providing a fallback string. If your i18n layer treats an empty string as a valid translation, these labels may render blank instead of falling back to English, and similar patterns appear for other new keys further down the file (webhook, password-policy, org-notifications, etc.).Please confirm the runtime behavior and either:
- rely on a documented “empty means fallback” mechanism, or
- temporarily populate these with English copies / remove the keys until proper translations are available.
messages/ko.json (1)
134-183: Review empty Korean translations for new webhook/security/password keysAs in the Hindi locale, several newly added keys here and further down (e.g.
add-webhook,allow-dev-builds,allow-device,allow-prod-builds, plus a number of webhook/password-policy/org-notification keys) are present with an empty string. Unless your i18n implementation explicitly falls back when the value is"", these may render as missing labels/tooltips instead of falling back to English.Consider confirming the fallback semantics and, if needed, temporarily populating these keys with English text or removing them until translations are ready.
messages/pt-br.json (1)
134-183: Confirm impact of empty PT‑BR strings on i18n fallbackNew keys added here and elsewhere in this file (e.g.
add-webhook, the variousallow-*-buildsandassigned, plus many webhook/password/notification keys) use""instead of localized or fallback text. Depending on your translation runtime, that can yield blank UI text rather than falling back to the English base strings.It’s worth confirming:
- whether empty values fall back automatically, and
- if not, whether you’d prefer to duplicate the English text for now or omit the keys until proper translations are provided.
messages/zh-cn.json (1)
134-183: Empty zh‑CN translations across new keys may lead to missing labelsAs with the other locales, several newly added zh‑CN keys (e.g.
add-webhook, the newallow-*flags, and many webhook/password/notification/setting keys lower in the file) are defined with empty-string values. If the i18n layer treats these as valid translations rather than “missing”, users may see blank labels/tooltips instead of English fallback.Please double-check how your message loader handles
"", and consider either:
- letting the key be absent until localized, or
- populating with the English text so at least something is rendered.
messages/fr.json (1)
134-135: Empty-string translations may suppress English fallback and render blank labelsMany newly added keys (for example
allow-dev-builds,allow-device,bundle-deployed, several password-policy and notification keys) are present but set to"". If your i18n stack treats an empty string as a valid translation (no fallback), any UI using these keys will show blank text in French.Consider either:
- copying the English text for now, or
- omitting keys from non-primary locales until you have proper translations so the default locale can safely fall back.
Also applies to: 173-182, 211-212, 280-281, 414-416, 428-429, 648-649, 769-775, 881-882, 907-908, 927-928, 941-943, 953-955, 969-979, 1042-1054, 1062-1065
messages/tr.json (1)
134-135: Review empty-string placeholders to avoid blank Turkish UI textA large number of new keys (e.g.
add-webhook,allow-dev-builds,allow-device, many password-policy and notification keys) are defined but set to"". If your localization layer does not fall back when a key exists but is empty, these will render as missing labels/tooltips in Turkish.Consider either:
- temporarily populating them with the English source text, or
- removing them until proper Turkish translations are ready so fallback behavior remains intact.
Also applies to: 173-182, 211-212, 280-281, 414-416, 428-429, 648-649, 769-775, 881-882, 907-908, 927-928, 941-943, 953-955, 969-979, 1042-1054, 1062-1065
messages/id.json (1)
134-135: Empty-string placeholders across many new keys may cause blank Indonesian UI stringsSimilar to the other locales, many newly introduced keys for webhooks, password policy, notifications, and security are present but set to
"". If your i18n handling does not fall back when a translation exists but is empty, any UI that uses those keys will show missing text in Indonesian.It’s worth auditing which of these keys are used in current UI and either:
- seed them with English source text, or
- drop them from this locale until proper translations are available.
Also applies to: 173-182, 211-212, 280-281, 414-416, 428-429, 648-649, 769-775, 881-882, 907-908, 927-928, 941-943, 953-955, 969-979, 1042-1054, 1062-1065
messages/de.json (1)
174-177: Tidy up empty/English fallbacks for German ancillary labels before features go liveA number of new keys are present but not localized, for example:
- Empty strings:
allow-dev-builds,allow-device,allow-prod-builds,assigned,bundle-deployed,characters,characters-minimum,completed-at,disabled, several password‑policy toggles (enable-password-policy,enable-policy,enforce-password-policy*,password-action-required, etc.),saving, and others.- Mixed language:
your-api-keyis"Your API Key"while the rest of the section is German.While most critical paths (2FA and webhook CRUD) are correctly translated, these placeholders will render as blank or English fragments in a German UI once you wire those features.
Suggested approach:
- For any key already used in UI, provide at least a basic German string or copy the English text as a temporary value, rather than leaving it
"".- Localize
your-api-key(e.g. “Dein API‑Schlüssel”) for consistency, unless you intentionally want the English phrasing.It’s worth double‑checking how your i18n runtime treats
""values; if they suppress fallback to the base language, you’ll want to avoid""for any user‑visible key.Also applies to: 211-212, 280-281, 414-416, 428-429, 685-686, 881-882, 1042-1043, 1053-1054, 1062-1065, 1182-1182, 1408-1408
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
messages/de.jsonmessages/es.jsonmessages/fr.jsonmessages/hi.jsonmessages/id.jsonmessages/it.jsonmessages/ja.jsonmessages/ko.jsonmessages/pl.jsonmessages/pt-br.jsonmessages/ru.jsonmessages/tr.jsonmessages/vi.jsonmessages/zh-cn.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:19.594Z
Learning: In the 2FA enforcement implementation for supabase/migrations: When an org has enforcing_2fa=true, all users including super_admins must have 2FA enabled before accessing any org functions (including check_org_members_2fa_enabled); this is intentional behavior to ensure consistent security enforcement without exceptions for admins.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run tests
- GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (17)
messages/hi.json (1)
22-24: 2FA enforcement messages look consistent and ready for UI useThe Hindi strings for
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowaccurately convey that the org requires 2FA for all members and should work correctly in the new enforcement/fail card flows. Based on learnings, this matches the intended strict 2FA behavior for all org members.Also applies to: 1238-1238
messages/ko.json (1)
22-24: Korean 2FA setup/enforcement copy aligns with new fail‑card behavior
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-noware clearly translated and communicate that the organization enforces 2FA for every member, which matches the enforcement rules used by the new UI.Also applies to: 1238-1238
messages/pt-br.json (1)
22-24: PT‑BR 2FA enforcement messaging is clear and matches product behaviorThe new strings for
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowread naturally in PT‑BR and clearly state that the org requires 2FA from all members, which should work well in the new enforcement card.Also applies to: 1238-1238
messages/zh-cn.json (1)
22-24: zh‑CN 2FA setup/enforcement keys are present and aligned with enforcementThe Chinese translations for
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-noware in place and correctly convey that the org enforces 2FA for all members, which should support the new fail/enforcement card UX.Also applies to: 1238-1238
messages/es.json (1)
22-23: 2FA enforcement messaging is accurate and aligned with org‑wide enforcement
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowclearly state that 2FA is required to access the organization and that the org requires 2FA for all members. This matches the enforcement behavior where no members (including super admins) are exempt once enforcement is enabled. Based on learnings, this is the correct framing for the fail/enforcement card.Also applies to: 1238-1238
messages/ja.json (1)
22-23: Japanese 2FA gating copy matches org‑wide enforcement semantics
2fa-setup-org-accessand2fa-setup-requiredclearly say that enabling 2FA is required to access the organization and that 2FA is required for all members;setup-2fa-nowis a clear CTA. This is consistent with the enforced behavior that every member, including admins, must have 2FA enabled before accessing org resources. Based on learnings, this is the intended behavior.Also applies to: 1238-1238
messages/vi.json (1)
22-23: Vietnamese 2FA enforcement text clearly communicates org access requirementThe new strings for
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowsay that two‑factor auth must be enabled to access the organization and that 2FA is required for all members. That matches the actual enforcement behavior (no exceptions, including for admins) and should work well for the 2FA fail card.Also applies to: 1238-1238
messages/ru.json (1)
22-23: Russian 2FA setup copy correctly reflects enforced access rules
2fa-setup-org-accessand2fa-setup-requiredexplain that 2FA must be enabled to access the organization and that the org requires 2FA for all members;setup-2fa-nowis a clear action label. This is consistent with the enforcement rule that no one, including super admins, can access org functions until they enable 2FA.Also applies to: 1238-1238
messages/fr.json (1)
22-23: 2FA enforcement messaging in French looks correct and aligned with behavior
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowclearly communicate that 2FA is mandatory for organization access and point users to the correct action; wording and tone are consistent with the rest of the French locale.Also applies to: 1238-1238
messages/tr.json (1)
22-23: Turkish 2FA enforcement texts are clear and accurate
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowcorrectly explain that 2FA is required for organization access and guide the user to configure it, matching the intended enforcement behavior.Also applies to: 1238-1238
messages/id.json (1)
22-23: Indonesian 2FA enforcement copy is consistent with the intended behavior
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowclearly state that 2FA is required to access the organization and instruct the user to configure it, matching the 2FA enforcement flow.Also applies to: 1238-1238
messages/pl.json (2)
22-23: 2FA enforcement messaging is clear and aligned with org‑wide requirementThe new Polish strings for
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowclearly explain that 2FA is mandatory for all org members and what the user must do, which matches the enforcement behavior.Also applies to: 1238-1238
322-323: Security, webhook, and password‑policy copy looks consistent where providedFor the keys where you did provide Polish text (e.g.
cannot-copy-secure-key,enforce-hashed-api-keys*,expose-metadata*, header/signature descriptions, password‑policy impact and verification messages), wording is technically accurate and consistent with the English semantics and the new enforcement behavior.Also applies to: 705-707, 736-738, 771-775, 1048-1069
messages/de.json (2)
22-23: German 2FA enforcement messaging correctly describes org‑wide requirementThe new
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowstrings clearly state that 2FA is required for all members to access the org and what action the user must take; this matches the intended enforcement semantics.Also applies to: 1238-1238
322-323: Webhook, hashed‑API‑key, and password‑policy German copy is technically soundFor the keys where you added German text (e.g.
cannot-copy-secure-key,enforce-hashed-api-keys*,expose-metadata*, webhook header/signature descriptions, password‑policy impact and verification messaging), the terminology and phrasing are accurate and consistent with the English behavior and security intent.Also applies to: 705-707, 736-738, 771-775, 1047-1061, 1242-1246
messages/it.json (2)
22-23: Italian 2FA enforcement copy is clear and matches behaviorThe new
2fa-setup-org-access,2fa-setup-required, andsetup-2fa-nowstrings clearly explain that 2FA is required for org access and prompt the user to configure it; this is consistent with the enforced 2FA behavior.Also applies to: 1238-1238
322-323: Security, webhook signature, and password‑verification Italian text is coherentWhere Italian translations are provided (e.g.
cannot-copy-secure-key,enforce-hashed-api-keys*,expose-metadata*, header/signature descriptions, and the password‑verification required/success messages), the terminology is accurate and consistent with the English intent and should work well with the new enforcement flows.Also applies to: 705-707, 736-738, 771-775, 1046-1061, 1242-1246
| "allow-dev-builds": "", | ||
| "allow-develoment-bui": "Permitir dispositivos de desarrollo", | ||
| "allow-device": "", | ||
| "allow-device-to-self": "Permitir que los dispositivos se disocien/asocien por sí mismos", | ||
| "allow-emulator": "Permitir Emuladores", | ||
| "allow-physical-device": "Permitir dispositivos físicos", | ||
| "allow-prod-build": "Permitir compilación de producción", | ||
| "allow-prod-builds": "", | ||
| "already-account": "¿Ya tienes una cuenta?", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, verify the file exists and get basic info
git ls-files | grep -E "messages.*es\.json"Repository: Cap-go/capgo
Length of output: 72
🏁 Script executed:
# Get the total line count to understand the file size
wc -l messages/es.jsonRepository: Cap-go/capgo
Length of output: 77
🏁 Script executed:
# Check a few of the line ranges mentioned to verify empty strings exist
echo "=== Lines 174-182 ==="
sed -n '174,182p' messages/es.json
echo "=== Lines 211-211 ==="
sed -n '211p' messages/es.json
echo "=== Lines 280-281 ==="
sed -n '280,281p' messages/es.json
echo "=== Lines 379-390 ==="
sed -n '379,390p' messages/es.jsonRepository: Cap-go/capgo
Length of output: 1582
🏁 Script executed:
# Count total empty string values in the file to understand the scope
grep -c '": ""' messages/es.jsonRepository: Cap-go/capgo
Length of output: 58
🏁 Script executed:
# Find the i18n implementation to understand how empty strings are handled
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) | xargs grep -l "i18n\|translation\|fallback" | head -10Repository: Cap-go/capgo
Length of output: 334
🏁 Script executed:
# Check the main i18n service
cat -n src/services/i18n.ts | head -100Repository: Cap-go/capgo
Length of output: 951
🏁 Script executed:
# Check the i18n module
cat -n src/modules/i18n.ts | head -100Repository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
# Search for how translations are resolved/loaded
rg "fallback|empty|default" src/services/i18n.ts -A 3 -B 3Repository: Cap-go/capgo
Length of output: 181
🏁 Script executed:
# Search for any fallback configuration in i18n files
rg "fallback" src/modules/i18n.ts src/services/i18n.ts -A 5 -B 5Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if there's a global i18n config or setup
rg "createI18n\|fallbackLocale" . --type ts --type tsx -A 10 -B 2Repository: Cap-go/capgo
Length of output: 83
🏁 Script executed:
# Look for where i18n might be configured beyond the module setup
fd "i18n\|locale" --type f -e ts -e tsx -e js | xargs grep -l "fallback" 2>/dev/nullRepository: Cap-go/capgo
Length of output: 40
🏁 Script executed:
# Check the English version to understand the structure
head -n 50 messages/en.jsonRepository: Cap-go/capgo
Length of output: 3234
🏁 Script executed:
# Verify if the review's claim about empty strings at all cited lines is accurate
echo "=== Checking all cited line ranges ===" && \
for range in "414-416" "577-578" "698-708" "1011-1024" "1053-1065" "1182-1182"; do
echo "Lines $range:";
sed -n "${range}p" messages/es.json | grep -c '": ""' || echo "0 empty strings";
doneRepository: Cap-go/capgo
Length of output: 627
🏁 Script executed:
# Use a different approach to check the additional line ranges
echo "=== Lines 414-416 ===" && sed -n '414,416p' messages/es.json
echo -e "\n=== Lines 577-578 ===" && sed -n '577,578p' messages/es.json
echo -e "\n=== Lines 698-708 ===" && sed -n '698,708p' messages/es.json
echo -e "\n=== Lines 1011-1024 ===" && sed -n '1011,1024p' messages/es.json
echo -e "\n=== Lines 1053-1065 ===" && sed -n '1053,1065p' messages/es.json
echo -e "\n=== Line 1182 ===" && sed -n '1182p' messages/es.jsonRepository: Cap-go/capgo
Length of output: 3847
🏁 Script executed:
# Check Vue i18n's actual behavior with empty strings by looking at templates/components
rg 'i18n\.\|$t\(' src --type ts --type js -A 2 -B 2 | head -50Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if there's a fallback locale configured anywhere
rg "fallbackLocale\|fallback.*locale" . --type ts --type js -iRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Search for usage of some of these empty-string keys in components
rg "allow-dev-builds|characters-minimum|enable-password-policy|password-policy-description|saving" src --type ts --type js -B 2 -A 2 | head -60Repository: Cap-go/capgo
Length of output: 4322
🏁 Script executed:
# Check if these keys are actually used in the UI (templates)
fd -e vue -e html | xargs grep -l "allow-dev-builds\|enable-password-policy\|password-policy" 2>/dev/null | head -10Repository: Cap-go/capgo
Length of output: 223
🏁 Script executed:
# Verify total count of empty strings again and understand the scale
echo "Total empty string translations:" && grep -c '": ""' messages/es.json
echo "" && echo "Sample of empty string keys:" && grep '": ""' messages/es.json | head -20Repository: Cap-go/capgo
Length of output: 664
Empty-string translations will render as blank in Spanish UI without fallback configuration
67 keys in this file are set to "", and Vue i18n has no fallback locale configured. Empty strings will render literally as blank text instead of falling back to English. This affects real UI elements: characters-minimum is used in ChangePassword.vue, enable-password-policy and password-policy-description are used in Security.vue, and several others appear in active components.
Consider either:
- Removing untranslated keys until translations are ready, or
- Temporarily copying the English strings so the UI remains usable for
es, then localizing later.
Also applies to: 211-211, 280-281, 379-390, 414-416, 698-708, 1053-1065, 1182-1182
| "your-api-key": "Your API Key", | ||
| "your-role-in-org": "Votre rôle dans l'organisation", | ||
| "your-settings": "Vos paramètres", | ||
| "your-usage": "Votre utilisation :", | ||
| "zip-bundle": "Paquet d'application Zip" |
There was a problem hiding this comment.
Localize "your-api-key" instead of leaving English text in the French bundle
The value "Your API Key" stands out as untranslated in an otherwise French UI and is likely visible in security/API-key flows.
Proposed French translation
- "your-api-key": "Your API Key",
+ "your-api-key": "Votre clé API",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "your-api-key": "Your API Key", | |
| "your-role-in-org": "Votre rôle dans l'organisation", | |
| "your-settings": "Vos paramètres", | |
| "your-usage": "Votre utilisation :", | |
| "zip-bundle": "Paquet d'application Zip" | |
| "your-api-key": "Votre clé API", | |
| "your-role-in-org": "Votre rôle dans l'organisation", | |
| "your-settings": "Vos paramètres", | |
| "your-usage": "Votre utilisation :", | |
| "zip-bundle": "Paquet d'application Zip" |
🤖 Prompt for AI Agents
In messages/fr.json around lines 1408 to 1412 the "your-api-key" entry is left
in English ("Your API Key"); replace the value with the French translation
(e.g., "Votre clé API") while preserving the JSON key, quotes, comma placement
and encoding; update the file so the line reads "your-api-key": "Votre clé API",
matching surrounding formatting.
| "your-api-key": "", | ||
| "your-role-in-org": "Peran Anda dalam organisasi", | ||
| "your-settings": "Pengaturan Anda", | ||
| "your-usage": "Penggunaan Anda:", | ||
| "zip-bundle": "Paket bundel aplikasi Zip" |
There was a problem hiding this comment.
Fill in "your-api-key" in Indonesian to avoid empty labels
Currently "your-api-key": "" will produce a blank string where this key is used, which is confusing in API/security UIs.
Proposed Indonesian translation
- "your-api-key": "",
+ "your-api-key": "Kunci API Anda",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "your-api-key": "", | |
| "your-role-in-org": "Peran Anda dalam organisasi", | |
| "your-settings": "Pengaturan Anda", | |
| "your-usage": "Penggunaan Anda:", | |
| "zip-bundle": "Paket bundel aplikasi Zip" | |
| "your-api-key": "Kunci API Anda", | |
| "your-role-in-org": "Peran Anda dalam organisasi", | |
| "your-settings": "Pengaturan Anda", | |
| "your-usage": "Penggunaan Anda:", | |
| "zip-bundle": "Paket bundel aplikasi Zip" |
🤖 Prompt for AI Agents
messages/id.json lines 1408-1412: the "your-api-key" value is an empty string
which yields a blank label in UIs; replace the empty value with the Indonesian
translation "Kunci API Anda" so the key reads "your-api-key": "Kunci API Anda",
ensuring the label displays correctly in API/security interfaces.
| "add-webhook": "", | ||
| "add-your-first-app-t": "Aggiungi la tua prima app al tuo account e iniziamo a inviare aggiornamenti!", | ||
| "add-your-first-bundle": "Aggiungi il tuo primo pacchetto al tuo account e procediamo con gli aggiornamenti!", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find the messages/it.json file and examine it
find . -name "it.json" -path "*/messages/*" 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 74
🏁 Script executed:
# Check the size and structure of the Italian translation file
if [ -f "messages/it.json" ]; then
echo "=== File info ==="
wc -l messages/it.json
echo ""
echo "=== First 20 lines ==="
head -20 messages/it.json
fiRepository: Cap-go/capgo
Length of output: 1937
🏁 Script executed:
# Run the provided script to find empty-string translations
rg -n '":\s*""' messages/*.json 2>/dev/null | head -50Repository: Cap-go/capgo
Length of output: 2672
🏁 Script executed:
# Check for empty strings specifically in it.json
rg -n '":\s*""' messages/it.json | head -100Repository: Cap-go/capgo
Length of output: 2503
🏁 Script executed:
# Also check the specific line ranges mentioned in the review
echo "=== Lines 134-136 ===" && sed -n '134,136p' messages/it.json
echo ""
echo "=== Lines 456-461 ===" && sed -n '456,461p' messages/it.json
echo ""
echo "=== Lines 627-637 ===" && sed -n '627,637p' messages/it.json
echo ""
echo "=== Lines 941-943 ===" && sed -n '941,943p' messages/it.jsonRepository: Cap-go/capgo
Length of output: 1203
🏁 Script executed:
# Let's check the i18n implementation to understand fallback behavior
find . -name "*.ts" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" | xargs grep -l "i18n\|locale\|fallback" 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 728
🏁 Script executed:
# Check the main i18n implementation
cat -n src/services/i18n.ts | head -100Repository: Cap-go/capgo
Length of output: 951
🏁 Script executed:
# Also check the i18n module
cat -n src/modules/i18n.ts | head -100Repository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
# Look for fallback logic and how empty strings are handled
rg -A 5 -B 5 "fallback\|empty\|''\|\"\"" src/services/i18n.ts src/modules/i18n.ts 2>/dev/null | head -150Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check for vue-i18n fallback configuration and how it handles empty strings
rg -n "fallback\|missingWarn\|fallbackWarn\|fallbackLocale" . --type ts --type js --type json 2>/dev/null | head -30Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Look at the actual usage of i18n in components to understand how translations are called
rg -n "\$t\(|t\(|i18n\.t" src/ --type vue --type ts -A 1 -B 1 2>/dev/null | head -50Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if there's any documentation or README about localization strategy
find . -name "*.md" -o -name "README*" | xargs grep -l "translation\|locali\|i18n" 2>/dev/nullRepository: Cap-go/capgo
Length of output: 88
🏁 Script executed:
# Check the messages README for localization documentation
cat messages/README.mdRepository: Cap-go/capgo
Length of output: 1037
🏁 Script executed:
# Look at vue-i18n configuration more thoroughly
rg -n "createI18n\|setLocaleMessage" . --type ts --type js -A 10 2>/dev/null | head -100Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if the i18n config has any fallback settings
cat -n src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
# Let's check how vue-i18n handles empty strings by default - search for interpolation or placeholder handling
rg -n "missing\|fall" src/ --type ts --type vue 2>/dev/null | grep -i "i18n\|locale\|translate" | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's verify vue-i18n default behavior by checking package.json
cat package.json | grep -A 2 -B 2 "vue-i18n"Repository: Cap-go/capgo
Length of output: 396
🏁 Script executed:
# Check if there's any example of how empty strings should be handled
rg -n "isEmpty|empty.*string|\"\"\s*translation" . --type ts --type vue --type json 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Look for any comments or documentation about empty translation values
rg -B 3 -A 3 "add-webhook\|create-webhook\|password-policy" messages/en.json | head -50Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check the English translation file for these keys to understand the expected behavior
grep -n "add-webhook\|create-webhook\|password-policy\|no-webhooks" messages/en.json | head -30Repository: Cap-go/capgo
Length of output: 1926
🏁 Script executed:
# Let's see how vue-i18n 11.1.12 handles empty strings - check if there's a missing message handler
rg -n "missingWarn\|fallback" . --type ts --type js --type json 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check for any i18n configuration in vite or nuxt config
find . -name "vite.config.*" -o -name "nuxt.config.*" -o -name ".vue-i18n.*" 2>/dev/null | xargs cat 2>/dev/null | head -100Repository: Cap-go/capgo
Length of output: 3025
🏁 Script executed:
# Check if there's a fallbackLocale configuration anywhere
rg -n "fallbackLocale\|fallback" . --type ts --type js --type json 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's check the entire vite.config.ts to see if there's any i18n configuration we missed
tail -200 vite.config.ts | head -100Repository: Cap-go/capgo
Length of output: 129
🏁 Script executed:
# Search for how vue-i18n is configured in the unplugin setup
rg -B 5 -A 5 "unplugin-vue-i18n" vite.config.tsRepository: Cap-go/capgo
Length of output: 110
🏁 Script executed:
# Count total empty strings in it.json vs other locales
echo "=== Empty strings count by locale ===" && \
for file in messages/*.json; do
locale=$(basename "$file" .json)
count=$(rg -c '":\s*""' "$file" 2>/dev/null || echo 0)
echo "$locale: $count"
done | sort -t: -k2 -rnRepository: Cap-go/capgo
Length of output: 203
🏁 Script executed:
# Find the vite config file with correct path
find . -name "vite.config.*" -type fRepository: Cap-go/capgo
Length of output: 73
🏁 Script executed:
# Check if there's a nuxt.config or any other config file that might set i18n fallback
find . -name "*.config.*" -type f | grep -v node_modules | grep -v dist | head -20Repository: Cap-go/capgo
Length of output: 263
🏁 Script executed:
# Look for Vue i18n default fallback behavior configuration in the codebase
rg -n "fallbackLocale\|fallback" src/ --type ts --type js 2>/dev/nullRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's verify how the i18n is actually used in components - check a sample component
find src/components -name "*.vue" -type f | head -5 | xargs cat 2>/dev/null | head -100Repository: Cap-go/capgo
Length of output: 3173
🏁 Script executed:
# Let's verify the exact vue-i18n configuration - check if there's a fallbackLocale in vite.config.mts
grep -n "fallbackLocale\|VueI18n" vite.config.mts -A 10 -B 2Repository: Cap-go/capgo
Length of output: 1094
🏁 Script executed:
# Check vue-i18n documentation by looking at how it handles empty strings in the actual codebase
rg -n "t(" src/ --type vue -B 2 -A 2 2>/dev/null | grep -A 4 "t(" | head -40Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Verify the actual behavior - look for any configuration that might handle missing translations
rg -n "missing\|missingWarn\|warnHtmlMessage" . --type ts --type js --type mts 2>/dev/nullRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's check the default behavior of vue-i18n by looking at vue-i18n documentation online
# First, let's verify the exact vue-i18n behavior by checking if there's any config that enables fallback
cat vite.config.mts | grep -A 30 "createI18n"Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if there's any fallback configuration in the actual i18n module setup
cat src/modules/i18n.ts | grep -A 5 -B 5 "createI18n"Repository: Cap-go/capgo
Length of output: 417
🏁 Script executed:
# Let's count how many of these empty-string keys are actually used in Vue components
rg -n "add-webhook|create-webhook|delete-webhook|password-policy|no-webhooks" src/ --type vue --type ts 2>/dev/null | head -30Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's verify the default vue-i18n behavior by checking if there's any documentation in comments
rg -n "fallback\|locale\|missing" src/modules/i18n.ts src/services/i18n.ts -B 3 -A 3 2>/dev/nullRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if empty strings are actually being used in the UI by looking for template usage
rg -n "no-webhooks|password-policy|add-webhook" src/ --type vue 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Verify the complete i18n initialization to see if fallbackLocale is set elsewhere
rg -rn "fallbackLocale" . --type ts --type mts --type js 2>/dev/nullRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's check vue-i18n default behavior by looking at the actual vue-i18n version in package.json
cat package.json | grep "vue-i18n"Repository: Cap-go/capgo
Length of output: 128
🏁 Script executed:
# Since fallbackLocale is not explicitly set, let's verify that these keys are actually used in components
# by searching for their usage patterns
rg -n "t\(['\"]add-webhook" src/ --type vue --type ts 2>/dev/nullRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check if there's any runtime fallback mechanism elsewhere
rg -n "fallback\|defaultMessage\|placeholder" src/ --type ts --type vue 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's verify the actual default behavior of vue-i18n 11.1.12 by checking if fallbackLocale defaults to 'en'
# Check the i18n module once more for any implicit fallback configuration
cat src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2051
🏁 Script executed:
# Check if there are any examples of empty string handling in any test files
find . -name "*.test.*" -o -name "*.spec.*" | xargs grep -l "i18n\|translation" 2>/dev/null | head -5Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Verify that these keys are actually being used in components - spot check for at least one
rg -n "add-webhook\|create-webhook\|delete-webhook\|no-webhooks\|password-policy" src/pages src/components --type vue 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's verify vue-i18n's default behavior by checking its documentation or any configuration we might have missed
# Check if there's any global config that sets fallbackLocale
rg -rn "fallback" . --type ts --type mts --type js --type json 2>/dev/null | grep -v node_modules | grep -v ".next" | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Let's also check if there's any missing message handler configured
rg -rn "missingWarn\|missing.*handler\|onWarn" . --type ts --type mts --type js 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Finally, let's verify that there are actual uses of these empty-string keys in the UI
find src/pages src/components -name "*.vue" -type f 2>/dev/null | xargs grep -l "webhook\|password-policy" | head -5Repository: Cap-go/capgo
Length of output: 261
🏁 Script executed:
# Let's check the Webhooks.vue component to see which keys it's using
grep -n "t(" src/pages/settings/organization/Webhooks.vue | head -30Repository: Cap-go/capgo
Length of output: 1719
🏁 Script executed:
# Check the PasswordPolicyWarningBanner.vue component
grep -n "t(" src/components/PasswordPolicyWarningBanner.vue | head -20Repository: Cap-go/capgo
Length of output: 203
🏁 Script executed:
# Check WebhookForm.vue
grep -n "t(" src/components/WebhookForm.vue | head -20Repository: Cap-go/capgo
Length of output: 1024
Empty Italian translations on webhook and password-policy features will display blank UI text
In it.json, 75 keys have empty string values "" including critical user-facing labels in webhook management and password policy enforcement. These keys are actively used in components like Webhooks.vue, WebhookForm.vue, and PasswordPolicyWarningBanner.vue.
Examples confirmed in use:
- Webhooks:
add-webhook,create-webhook,delete-webhook,delete-webhook-confirm,edit-webhook,no-webhooks,no-webhooks-description - Password policy:
password-policy,password-policy-required,password-policy-required-message,password-policy-description,password-update-org-access,password-action-required,password-change-then-verify - Controls:
allow-dev-builds,allow-device,allow-prod-builds,assigned,characters,disabled,removed,retry,saving
The i18n configuration does not specify a fallbackLocale, so empty strings render as blank text rather than falling back to English. Italian users will encounter missing labels and descriptive text in these features.
Recommended actions:
- Provide Italian translations for these keys instead of empty strings, or
- Remove the keys from
it.jsonentirely to enable fallback to English
Also localize your-api-key (e.g., "La tua chiave API") for consistency.
Full list of affected lines
134-136, 174, 176, 181, 211, 280, 307, 379, 382-383, 388-389, 414-415, 428, 456, 460, 627-628, 633-637, 685, 694, 698-699, 707-708, 718, 731, 742, 767, 769-770, 881, 907, 927, 941-942, 993-995, 1042-1043, 1049-1051, 1053, 1056-1057, 1062-1065, 1069, 1138, 1147, 1151, 1155-1157, 1165, 1169, 1182, 1206, 1235-1236, 1240, 1263, 1273, 1319, 1346, 1348, 1364
🤖 Prompt for AI Agents
In messages/it.json around lines 134 to 136 (and other listed lines), many keys
(including add-webhook and several password-policy and control labels) are set
to empty strings causing blank UI text; replace each empty value with the proper
Italian translation (or remove the key entirely to allow fallback to English) —
specifically fill in translations for webhook keys (add-webhook, create-webhook,
delete-webhook, delete-webhook-confirm, edit-webhook, no-webhooks,
no-webhooks-description), password-policy keys (password-policy,
password-policy-required, password-policy-required-message,
password-policy-description, password-update-org-access,
password-action-required, password-change-then-verify), control labels
(allow-dev-builds, allow-device, allow-prod-builds, assigned, characters,
disabled, removed, retry, saving) and also localize your-api-key (e.g., "La tua
chiave API"); ensure no empty string values remain for keys referenced by the
app or remove them so the i18n fallback to English works.
| "allow-dev-builds": "", | ||
| "allow-develoment-bui": "開発ビルドを許可する", | ||
| "allow-device": "", | ||
| "allow-device-to-self": "デバイスに自己分離/関連付けを許可する", | ||
| "allow-emulator": "エミュレータを許可する", | ||
| "allow-physical-device": "実機を許可", | ||
| "allow-prod-build": "本番ビルドを許可", | ||
| "allow-prod-builds": "", | ||
| "already-account": "すでにアカウントをお持ちですか?", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git ls-files messages/ | head -20Repository: Cap-go/capgo
Length of output: 335
🏁 Script executed:
wc -l messages/ja.jsonRepository: Cap-go/capgo
Length of output: 77
🏁 Script executed:
sed -n '174,182p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 365
🏁 Script executed:
sed -n '210,212p' messages/ja.json
sed -n '279,282p' messages/ja.json
sed -n '379,391p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 960
🏁 Script executed:
sed -n '414,416p' messages/ja.json
sed -n '577,578p' messages/ja.json
sed -n '698,708p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 648
🏁 Script executed:
sed -n '1011,1024p' messages/ja.json
sed -n '1053,1065p' messages/ja.json
sed -n '1182p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 1681
🏁 Script executed:
# Look at en.json to see what should be translated
sed -n '174,182p' messages/en.jsonRepository: Cap-go/capgo
Length of output: 309
🏁 Script executed:
# Find how i18n is implemented
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.vue" \) | xargs grep -l "i18n\|i18next\|vue-i18n" | head -10Repository: Cap-go/capgo
Length of output: 362
🏁 Script executed:
# Check en.json for comparison at the line ranges mentioned
sed -n '414,416p' messages/en.json
sed -n '577,578p' messages/en.json
sed -n '698,708p' messages/en.jsonRepository: Cap-go/capgo
Length of output: 710
🏁 Script executed:
# Find i18n configuration
find . -type f \( -name "*.ts" -o -name "*.js" \) | xargs grep -l "createI18n\|i18n:" | head -5Repository: Cap-go/capgo
Length of output: 77
🏁 Script executed:
# Check package.json for i18n library
grep -i "i18n\|vue-i18n" package.jsonRepository: Cap-go/capgo
Length of output: 159
🏁 Script executed:
# Check the main i18n configuration
find . -type f -name "*i18n*" | grep -v node_modules | head -10Repository: Cap-go/capgo
Length of output: 100
🏁 Script executed:
# Examine the i18n configuration
cat -n ./src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
cat -n ./src/services/i18n.tsRepository: Cap-go/capgo
Length of output: 951
🏁 Script executed:
# Check remaining line ranges
sed -n '1011,1024p' messages/ja.json
sed -n '1053,1065p' messages/ja.json
sed -n '1182p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 1681
🏁 Script executed:
# Search for any fallbackLocale configuration
grep -r "fallbackLocale" . --include="*.ts" --include="*.js" | grep -v node_modulesRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Count empty strings in ja.json
grep -c '": ""' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 58
🏁 Script executed:
# Compare with en.json to see how many keys have translations in English
grep -c '": ""' messages/en.jsonRepository: Cap-go/capgo
Length of output: 57
🏁 Script executed:
# See what's at lines 1011-1024, 1053-1065, 1182 again
sed -n '1011,1024p' messages/ja.json
sed -n '1053,1065p' messages/ja.json
sed -n '1182p' messages/ja.jsonRepository: Cap-go/capgo
Length of output: 1681
Remove or populate 75 untranslated empty-string keys in ja.json to prevent blank UI text
ja.json contains 75 empty-string values (e.g., "allow-dev-builds": ""), while the English source (en.json) has complete translations for all keys. Since no fallbackLocale is configured in the i18n setup, empty strings are treated as valid translations. Japanese users will see blank labels and messages in the UI instead of falling back to English.
Either remove untranslated keys from ja.json until translations are ready, or temporarily copy English values as placeholders for later localization. This affects password-policy screens, org-notifications, webhook delivery/help text, and other critical UI elements.
Affected line ranges: 174-182, 211, 280-281, 379-390, 414-416, 577-578, 698-708, 1011-1024, 1053-1065, 1182.
🤖 Prompt for AI Agents
In messages/ja.json around lines 174-182 (and affected ranges 211, 280-281,
379-390, 414-416, 577-578, 698-708, 1011-1024, 1053-1065, 1182) there are 75
keys with empty-string values causing blank UI text; either remove those
untranslated keys from ja.json so the app will fall back to the source locale,
or populate them with the English source strings from en.json as temporary
placeholders. Update only the empty values (copy the corresponding en.json
value) or delete the key entirely, then run the i18n validation/lint script (or
a quick grep for '": ""') to confirm no remaining empty translations and commit
the cleaned ja.json.
| "add-webhook": "", | ||
| "add-your-first-app-t": "Dodaj swoją pierwszą aplikację do swojego konta i zacznijmy wprowadzać aktualizacje!", | ||
| "add-your-first-bundle": "Dodaj swoją pierwszą paczkę do swojego konta i zacznijmy wprowadzać aktualizacje!", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, check if the file exists and its total line count
wc -l messages/pl.jsonRepository: Cap-go/capgo
Length of output: 77
🏁 Script executed:
#!/bin/bash
# Check the specific lines mentioned in the comment
# Lines 134-136
echo "=== Lines 134-136 ==="
sed -n '134,136p' messages/pl.json
# Lines 280-281
echo "=== Lines 280-281 ==="
sed -n '280,281p' messages/pl.json
# Lines 627-637
echo "=== Lines 627-637 ==="
sed -n '627,637p' messages/pl.json
# Lines 941-943
echo "=== Lines 941-943 ==="
sed -n '941,943p' messages/pl.json
# Lines 1042-1047
echo "=== Lines 1042-1047 ==="
sed -n '1042,1047p' messages/pl.json
# Lines 1182-1183
echo "=== Lines 1182-1183 ==="
sed -n '1182,1183p' messages/pl.json
# Lines 1198-1202
echo "=== Lines 1198-1202 ==="
sed -n '1198,1202p' messages/pl.json
# Lines 1263-1264
echo "=== Lines 1263-1264 ==="
sed -n '1263,1264p' messages/pl.json
# Lines 1408-1412
echo "=== Lines 1408-1412 ==="
sed -n '1408,1412p' messages/pl.jsonRepository: Cap-go/capgo
Length of output: 2130
🏁 Script executed:
#!/bin/bash
# Run the suggested helper script to see all empty translations
rg -n '":\s*""' messages/pl.json | head -50Repository: Cap-go/capgo
Length of output: 1672
🏁 Script executed:
#!/bin/bash
# Check for specific keys mentioned but not verified in line ranges
echo "=== Checking for password-policy related keys ==="
rg -n 'password-policy|password-update-org-access|update-password-now' messages/pl.json
echo "=== Checking for allow-* keys ==="
rg -n 'allow-dev-builds|allow-device|allow-prod-builds' messages/pl.json
echo "=== Checking for generic control keys ==="
rg -n '"assigned"|"characters"|"characters-minimum"|"completed-at"|"removed"|"retry"' messages/pl.jsonRepository: Cap-go/capgo
Length of output: 1570
Empty Polish translations for user‑visible keys will likely render blank UI
Multiple keys in messages/pl.json have empty string ("") values that are used in shipped UI. These empty translations will render as blank elements instead of falling back to the default locale if your i18n runtime treats empty strings as defined translations—which is the common behavior.
Affected areas include:
- Webhook UI:
add-webhook,create-first-webhook,create-webhook,delete-webhook,delete-webhook-confirm,delivery-id,delivery-log,delivery-retry-failed,delivery-retry-queued,no-webhooks,no-webhooks-description,subscribed-events - Password policy / security:
password-action-required,password-change-then-verify,password-policy,password-policy-description,password-policy-required,password-policy-updated,password-update-org-access,enable-password-policy,enforce-password-policy,enforce-password-policy-description, and requirement flags (minimum-length,one-number,one-uppercase,one-special-character) - Generic controls:
allow-dev-builds,allow-device,allow-prod-builds,assigned,characters,characters-minimum,completed-at,removed,retry,saving
Either provide non-empty fallbacks (Polish or English) for all user-facing keys, or remove these keys from pl.json until translations are ready so the runtime can fall back to the base language.
🤖 Prompt for AI Agents
In messages/pl.json around lines 134 to 136, several user‑visible keys
(including "add-webhook" and many others listed in the review) are set to empty
strings which will render blank in the UI; replace each empty value with a
proper Polish translation or a safe fallback (e.g., the English base string) for
every affected key, or remove those keys from pl.json entirely until
translations are ready so the i18n runtime will fall back to the default locale.
Ensure you update all listed keys (webhook UI keys, password policy/security
keys, and generic control keys) consistently and run a quick i18n spot-check to
confirm no empty strings remain.
| "add-webhook": "", | ||
| "add-your-first-app-t": "Добавьте свое первое приложение в свой аккаунт и давайте отправлять обновления!", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd /tmp && find . -name "ru.json" -type f 2>/dev/null | head -5Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
find . -name "ru.json" -type f 2>/dev/nullRepository: Cap-go/capgo
Length of output: 74
🏁 Script executed:
git ls-files | grep -E "ru\.json|messages"Repository: Cap-go/capgo
Length of output: 335
🏁 Script executed:
# First get file stats
wc -l messages/ru.json
# Check lines around 134-135
sed -n '130,140p' messages/ru.json
# Check a few more sections mentioned
sed -n '170,185p' messages/ru.json
sed -n '275,285p' messages/ru.jsonRepository: Cap-go/capgo
Length of output: 1943
🏁 Script executed:
# Find i18n or translation related files
find . -type f \( -name "*i18n*" -o -name "*translat*" -o -name "*locale*" \) ! -path "*/node_modules/*" 2>/dev/null | head -20Repository: Cap-go/capgo
Length of output: 153
🏁 Script executed:
# Look for how translations are loaded/used
rg -l "ru\.json|i18n|translation" --type json --type js --type ts | head -20Repository: Cap-go/capgo
Length of output: 588
🏁 Script executed:
# Search for how empty strings are handled in i18n
rg "empty.*string|fallback.*english|gettext|i18n" --type js --type ts -A 3 | head -50Repository: Cap-go/capgo
Length of output: 3722
🏁 Script executed:
# List root directory
ls -la
# Check for package.json to understand the i18n library
cat package.json | grep -A 5 -B 5 "i18n\|translat"Repository: Cap-go/capgo
Length of output: 5518
🏁 Script executed:
# Also search for common i18n libraries usage
rg "i18next|react-intl|format\.js|gettext" package.jsonRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Get file size and structure
stat messages/ru.json
# Check if there are empty string values
rg '^[[:space:]]*"[^"]+"\s*:\s*""\s*,$' messages/ru.json | head -20
# Also check for the specific keys mentioned
rg '"(add-webhook|delete-webhook|allow-dev-builds|allow-device)"' messages/ru.jsonRepository: Cap-go/capgo
Length of output: 748
🏁 Script executed:
# Search for imports and usage of messages files
rg "messages.*ru\|ru\.json" --type js --type ts --type jsx --type tsx -B 2 -A 2 | head -30Repository: Cap-go/capgo
Length of output: 83
🏁 Script executed:
# Search for how fallback is handled
rg "defaultMessage|fallback.*message|missing.*translation|empty.*value" --type js --type ts -A 3 | head -40Repository: Cap-go/capgo
Length of output: 677
🏁 Script executed:
# Look for English translation file
find . -name "*en*" -path "*/messages/*" | head -10
# Get file listing of messages directory
ls -la messages/Repository: Cap-go/capgo
Length of output: 1162
🏁 Script executed:
# Compare structure of English and Russian files
head -20 messages/en.json
wc -l messages/en.json messages/ru.jsonRepository: Cap-go/capgo
Length of output: 1737
🏁 Script executed:
# Look for i18n setup/config
find . -type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) ! -path "*/node_modules/*" -exec grep -l "i18n\|messages\|locale\|translation" {} \; | head -15Repository: Cap-go/capgo
Length of output: 1011
🏁 Script executed:
# Search for how messages are accessed
rg "messages\[|messages\.|formatMessage|translate" --type js --type ts --max-count 10 -B 2 -A 2Repository: Cap-go/capgo
Length of output: 21420
🏁 Script executed:
# Check for webpack, vite, or other config that might process JSON files
ls -la | grep -E "webpack|vite|build|config"
# Look in src directory structure
find . -maxdepth 3 -type d ! -path "*/node_modules/*" | head -20Repository: Cap-go/capgo
Length of output: 1142
🏁 Script executed:
# Read the first 200 lines to understand structure
head -200 messages/ru.json | tail -70Repository: Cap-go/capgo
Length of output: 4222
🏁 Script executed:
# Count empty string values in ru.json
rg ':\s*""\s*[,}]' messages/ru.json | wc -l
# Show actual empty string keys
rg ':\s*""\s*[,}]' messages/ru.json | head -30Repository: Cap-go/capgo
Length of output: 887
🏁 Script executed:
# Compare specific keys between English and Russian
python3 << 'EOF'
import json
with open('messages/en.json', 'r') as f:
en = json.load(f)
with open('messages/ru.json', 'r') as f:
ru = json.load(f)
# Find keys in ru that are empty
empty_keys = [k for k, v in ru.items() if v == ""]
print(f"Total empty string keys in ru.json: {len(empty_keys)}")
print("\nEmpty keys (first 20):")
for key in empty_keys[:20]:
en_val = en.get(key, "[KEY_NOT_IN_EN]")
print(f" {key}: EN='{en_val[:50]}...' RU=''")
# Show the specific keys mentioned in the review
mentioned_keys = ["add-webhook", "delete-webhook", "delete-webhook-confirm", "create-first-webhook",
"create-webhook", "allow-dev-builds", "allow-device", "allow-prod-builds", "disabled"]
print("\n\nKeys mentioned in review:")
for key in mentioned_keys:
if key in ru:
print(f" {key}: empty={ru[key] == ''}, value='{ru[key]}'")
else:
print(f" {key}: NOT FOUND IN RU.JSON")
EOFRepository: Cap-go/capgo
Length of output: 142
🏁 Script executed:
# Search for the i18n implementation/loader
find . -type f \( -name "*.js" -o -name "*.ts" \) ! -path "*/node_modules/*" | xargs grep -l "messages" | grep -v test | head -10Repository: Cap-go/capgo
Length of output: 387
🏁 Script executed:
# Look at the structure of src or app directory
find . -maxdepth 2 -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" | grep -v node_modules | head -15Repository: Cap-go/capgo
Length of output: 423
🏁 Script executed:
# Check package.json more carefully
cat package.json | head -50Repository: Cap-go/capgo
Length of output: 3491
🏁 Script executed:
# Search for actual usage of the message keys
rg "add-webhook|delete-webhook" --type js --type ts --type jsx --type tsx | head -20Repository: Cap-go/capgo
Length of output: 83
🏁 Script executed:
# Show the exact lines mentioned in the review
echo "=== Lines 134-135 ==="
sed -n '134,135p' messages/ru.json
echo -e "\n=== Lines 174-182 ==="
sed -n '174,182p' messages/ru.json
echo -e "\n=== Line 211 ==="
sed -n '211p' messages/ru.json
echo -e "\n=== Lines 280-281 ==="
sed -n '280,281p' messages/ru.json
echo -e "\n=== Lines 379-390 ==="
sed -n '379,390p' messages/ru.jsonRepository: Cap-go/capgo
Length of output: 1669
🏁 Script executed:
# Check the i18n module setup
cat src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2051
🏁 Script executed:
# Check the i18n service
cat src/services/i18n.tsRepository: Cap-go/capgo
Length of output: 741
🏁 Script executed:
# Look for vue-i18n configuration
grep -r "fallback\|missingHandler" --include="*.ts" --include="*.js" | grep -v node_modulesRepository: Cap-go/capgo
Length of output: 1370
🏁 Script executed:
# Check how i18n is initialized in the app
find src -type f \( -name "main.ts" -o -name "app.ts" -o -name "index.ts" \) | head -5 | xargs cat 2>/dev/null | head -100Repository: Cap-go/capgo
Length of output: 4795
🏁 Script executed:
cat project.inlang/settings.jsonRepository: Cap-go/capgo
Length of output: 900
🏁 Script executed:
# Look at how the t() function is used and if there's any fallback logic
grep -n "const.*t.*=" src/modules/i18n.ts | head -20
# Check how locales are loaded
cat src/modules/i18n.ts | head -80Repository: Cap-go/capgo
Length of output: 2144
🏁 Script executed:
# Search for any custom missing handler or fallback logic
rg "missing.*handler|fallback|empty.*string" src/ --type ts -B 2 -A 2Repository: Cap-go/capgo
Length of output: 697
🏁 Script executed:
cat project.inlang/settings.jsonRepository: Cap-go/capgo
Length of output: 900
🏁 Script executed:
# Check vite config for i18n setup
cat vite.config.mts | grep -A 20 "i18n"Repository: Cap-go/capgo
Length of output: 1607
🏁 Script executed:
# Search for createI18n call
rg "createI18n" src/ --type ts -B 5 -A 10Repository: Cap-go/capgo
Length of output: 1052
🏁 Script executed:
wc -l src/modules/i18n.ts src/services/i18n.ts
head -100 src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2113
🏁 Script executed:
tail -50 src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 1351
🏁 Script executed:
# Look for tests related to i18n
find . -path "*/node_modules" -prune -o -name "*i18n*.test.ts" -type f -print
# Check messages README
cat messages/README.mdRepository: Cap-go/capgo
Length of output: 1037
🏁 Script executed:
# Search for how the application currently handles missing/empty translations
rg "useI18n\|i18n\.t" src/pages/ --type vue -A 2 | head -30Repository: Cap-go/capgo
Length of output: 83
🏁 Script executed:
# Sample a component to see how translations are accessed
head -80 src/pages/settings/organization/Webhooks.vue | tail -40Repository: Cap-go/capgo
Length of output: 1121
🏁 Script executed:
# Look for i18n initialization
grep -r "new VueI18n\|createI18n" src/ --include="*.ts" -B 5 -A 15Repository: Cap-go/capgo
Length of output: 1292
🏁 Script executed:
# Check the services/i18n.ts
cat src/services/i18n.tsRepository: Cap-go/capgo
Length of output: 741
🏁 Script executed:
cat src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2051
🏁 Script executed:
find src -name "*.ts" -o -name "*.vue" | xargs grep -l "i18n\|I18n" | head -10Repository: Cap-go/capgo
Length of output: 362
🏁 Script executed:
# Get context around i18n usage in main entry
grep -r "createI18n\|i18n\.global\|setLocaleMessage" src/ --include="*.ts" --include="*.js" -B 3 -A 8 | head -50Repository: Cap-go/capgo
Length of output: 2563
🏁 Script executed:
cat vite.config.mts | head -150Repository: Cap-go/capgo
Length of output: 4299
🏁 Script executed:
# Find the main entry point
find src -maxdepth 2 -name "*.ts" -o -name "*.js" | xargs grep -l "createApp\|new Vue" | head -5Repository: Cap-go/capgo
Length of output: 89
🏁 Script executed:
# Look for app initialization
ls -la src/ | head -20
cat index.html | head -30Repository: Cap-go/capgo
Length of output: 2456
🏁 Script executed:
# Find where the app is created
rg "createApp" src/ --type ts -B 2 -A 10 | head -40Repository: Cap-go/capgo
Length of output: 2301
🏁 Script executed:
# Get a summary of empty strings by category from the review
python3 << 'EOF'
import json
with open('messages/en.json', 'r') as f:
en = json.load(f)
with open('messages/ru.json', 'r') as f:
ru = json.load(f)
# Find keys in ru that are empty
empty_keys = [k for k, v in ru.items() if v == ""]
webhook_keys = [k for k in empty_keys if 'webhook' in k]
toggle_keys = [k for k in empty_keys if k in ['allow-dev-builds', 'allow-device', 'allow-prod-builds', 'disabled']]
password_keys = [k for k in empty_keys if 'password' in k or 'characters' in k or 'minimum' in k or 'users-' in k]
delivery_keys = [k for k in empty_keys if 'delivery' in k]
print(f"Total empty string keys: {len(empty_keys)}\n")
print(f"Webhook-related: {len(webhook_keys)} - {webhook_keys}")
print(f"\nToggle/setting helpers: {len(toggle_keys)} - {toggle_keys}")
print(f"\nPassword/requirements: {len(password_keys)} - {password_keys}")
print(f"\nDelivery-related: {len(delivery_keys)} - {delivery_keys}")
# Show what the English versions say
print("\n\nSample translations missing:")
for key in webhook_keys[:3]:
print(f" {key}: '{en.get(key, '[NOT FOUND]')}'")
EOFRepository: Cap-go/capgo
Length of output: 1254
🏁 Script executed:
# Check if there's a fallback language configuration
rg "fallbackLocale|fallback" src/modules/ src/services/ --type ts -B 2 -A 2Repository: Cap-go/capgo
Length of output: 469
🏁 Script executed:
# Check localesMap to see how locales are loaded
grep -A 20 "localesMap" src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 1124
🏁 Script executed:
cat -n src/modules/i18n.ts | head -60Repository: Cap-go/capgo
Length of output: 2185
🏁 Script executed:
cat -n src/services/i18n.tsRepository: Cap-go/capgo
Length of output: 951
Multiple new keys use empty strings, which will render as blank text instead of showing English fallback
In ru.json, 76 keys are defined with empty string values, including:
- Webhook UI:
add-webhook,delete-webhook,delete-webhook-confirm,create-first-webhook,create-webhook, and delivery-related labels - Toggle/setting helpers:
allow-dev-builds,allow-device,allow-prod-builds,disabled - Password policy & requirements:
characters,characters-minimum,enable-password-policy,enforce-password-policy-description, and 19 others - Channel and org settings
Vue I18n is configured without a fallback locale, so empty strings render as blank text rather than falling back to English. This affects usability on Russian locale, especially for security features (2FA enforcement, password policies) and critical workflows (webhooks, delivery logs).
Either remove untranslated keys from ru.json until they're ready for translation, or fill them with English text as placeholders and track them for translation.
🤖 Prompt for AI Agents
messages/ru.json around lines 134-135: multiple keys (including "add-webhook" at
134) are set to empty strings which causes blank UI text because Vue I18n has no
fallback; remove these untranslated keys from ru.json or populate them with
English placeholder values (e.g., duplicate the en.json value) for all empty
entries, and track them for translation so Russian locale renders readable text
until proper translations are provided.
| "your-api-key": "", | ||
| "your-role-in-org": "Organizasyondaki rolünüz", | ||
| "your-settings": "Ayarlarınız", | ||
| "your-usage": "Kullanımınız:", | ||
| "zip-bundle": "Zip uygulama paketi" |
There was a problem hiding this comment.
Provide a Turkish value for "your-api-key" instead of leaving it empty
"your-api-key": "" will likely show as an empty label wherever this key is used (e.g., API key dialogs), which is confusing for users.
Proposed Turkish translation
- "your-api-key": "",
+ "your-api-key": "API anahtarınız",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "your-api-key": "", | |
| "your-role-in-org": "Organizasyondaki rolünüz", | |
| "your-settings": "Ayarlarınız", | |
| "your-usage": "Kullanımınız:", | |
| "zip-bundle": "Zip uygulama paketi" | |
| "your-api-key": "API anahtarınız", | |
| "your-role-in-org": "Organizasyondaki rolünüz", | |
| "your-settings": "Ayarlarınız", | |
| "your-usage": "Kullanımınız:", | |
| "zip-bundle": "Zip uygulama paketi" |
🤖 Prompt for AI Agents
In messages/tr.json around lines 1408 to 1412, the "your-api-key" entry is an
empty string; replace it with an appropriate Turkish translation (for example:
"API anahtarınız") so the label displays correctly wherever used; update the
value only, keep the key unchanged and ensure the string follows the project's
quoting/formatting conventions.
| "allow-dev-builds": "", | ||
| "allow-develoment-bui": "Cho phép xây dựng phát triển", | ||
| "allow-device": "", | ||
| "allow-device-to-self": "Cho phép thiết bị tự ngắt kết nối/kết nối", | ||
| "allow-emulator": "Cho phép giả lập", | ||
| "allow-physical-device": "Cho phép thiết bị vật lý", | ||
| "allow-prod-build": "Cho phép bản build sản xuất", | ||
| "allow-prod-builds": "", | ||
| "already-account": "Bạn đã có tài khoản chưa?", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find the messages directory and confirm the vi.json file exists
find . -name "vi.json" -o -name "messages" -type d | head -20Repository: Cap-go/capgo
Length of output: 85
🏁 Script executed:
# Get the overall structure of the repository
git ls-files | grep -E "(messages|i18n|locale|translation)" | head -30Repository: Cap-go/capgo
Length of output: 376
🏁 Script executed:
# Check the messages directory
ls -la messages/ 2>/dev/null || echo "Checking alternative paths..."Repository: Cap-go/capgo
Length of output: 1143
🏁 Script executed:
# Check the vi.json file at the specific line ranges mentioned
wc -l messages/vi.jsonRepository: Cap-go/capgo
Length of output: 77
🏁 Script executed:
# Extract and examine the specific line ranges
echo "=== Lines 174-182 ===" && sed -n '174,182p' messages/vi.json
echo ""
echo "=== Lines 211 ===" && sed -n '211p' messages/vi.json
echo ""
echo "=== Lines 280-281 ===" && sed -n '280,281p' messages/vi.json
echo ""
echo "=== Lines 379-390 ===" && sed -n '379,390p' messages/vi.json
echo ""
echo "=== Lines 414-416 ===" && sed -n '414,416p' messages/vi.json
echo ""
echo "=== Lines 577-578 ===" && sed -n '577,578p' messages/vi.jsonRepository: Cap-go/capgo
Length of output: 1673
🏁 Script executed:
# Continue checking remaining line ranges
echo "=== Lines 698-708 ===" && sed -n '698,708p' messages/vi.json
echo ""
echo "=== Lines 1011-1024 ===" && sed -n '1011,1024p' messages/vi.json
echo ""
echo "=== Lines 1053-1065 ===" && sed -n '1053,1065p' messages/vi.json
echo ""
echo "=== Lines 1182 ===" && sed -n '1182p' messages/vi.jsonRepository: Cap-go/capgo
Length of output: 3015
🏁 Script executed:
# Check the i18n module and service files
cat messages/README.mdRepository: Cap-go/capgo
Length of output: 1037
🏁 Script executed:
# Examine the i18n module
cat -n src/modules/i18n.ts | head -100Repository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
# Check i18n service
cat -n src/services/i18n.ts | head -150Repository: Cap-go/capgo
Length of output: 951
🏁 Script executed:
# Look for any fallback configuration or missing key handling
rg -A 5 -B 5 "fallback\|missing\|missing-key" src/ --type ts --type jsRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check how i18n is used in templates/components to see if there's any fallback logic
rg "i18n\|t\(" src/ --type vue --type ts | head -20Repository: Cap-go/capgo
Length of output: 83
🏁 Script executed:
# Look for the createI18n config more thoroughly
rg "createI18n\|i18n\." src/modules/i18n.ts -A 15Repository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Check for any vue-i18n fallback or missing message handlers
rg "missingWarn\|fallbackLocale\|fallback" --type ts --type jsRepository: Cap-go/capgo
Length of output: 38
🏁 Script executed:
# Look at the entire createI18n configuration in i18n.ts
cat -n src/modules/i18n.tsRepository: Cap-go/capgo
Length of output: 2548
🏁 Script executed:
# Compare empty strings in vi.json vs en.json for the same keys
echo "=== Checking corresponding keys in en.json ===" && \
sed -n '174,182p' messages/en.json && \
echo "" && \
sed -n '414,416p' messages/en.json && \
echo "" && \
sed -n '1053,1065p' messages/en.jsonRepository: Cap-go/capgo
Length of output: 1169
🏁 Script executed:
# Search for specific empty string keys in vi.json and compare with en.json
echo "=== Checking 'allow-dev-builds' ===" && \
rg '"allow-dev-builds"' messages/en.json messages/vi.json && \
echo "" && \
echo "=== Checking 'password-policy' ===" && \
rg '"password-policy"' messages/en.json messages/vi.json && \
echo "" && \
echo "=== Checking 'characters' ===" && \
rg '"characters"' messages/en.json messages/vi.jsonRepository: Cap-go/capgo
Length of output: 443
🏁 Script executed:
# Count empty string values in vi.json and compare with en.json
echo "Empty strings in vi.json:" && \
rg '": ""' messages/vi.json | wc -l && \
echo "Empty strings in en.json:" && \
rg '": ""' messages/en.json | wc -lRepository: Cap-go/capgo
Length of output: 112
🏁 Script executed:
# Search vue-i18n documentation behavior regarding empty strings and missing keys
web_search
vue-i18n behavior empty string values fallback to english default localeRepository: Cap-go/capgo
Length of output: 153
🌐 Web query:
vue-i18n empty string fallback behavior missing translation
💡 Result:
Short answer: By default vue-i18n treats an empty string as a valid (present) translation and will NOT fall back to another locale — so an empty-string message will be returned instead of using the fallback locale. Recent versions add explicit options to change that behaviour.
Details and how to fix it
- Legacy vue-i18n considered an empty string as translated (no fallback). See the GitHub issue discussing this behavior. [1]
- Newer vue-i18n releases expose controls: e.g. fallbackRootWithEmptyString (added v8.26+) lets you decide whether an empty string should fall back to root/global messages. The docs also explain fallbackLocale behavior and related warnings. [2][3]
- Note: the v9 docs call out differences in default empty-string fallback behavior vs earlier versions — check the version of vue-i18n you use and set fallbackRootWithEmptyString (or configure fallbackLocale / missing handlers) accordingly. [2][4]
References
- GitHub issue: Change the way missing translation keys are detected. [1]
- Vue I18n guide — Fallbacking (official docs). [2]
- Vue I18n API reference (fallbackRoot / fallbackRootWithEmptyString explanation). [3]
- Legacy repo fallback docs. [4]
🌐 Web query:
vue-i18n default fallback locale configuration
💡 Result:
Short summary — how to configure Vue I18n fallback locale
-
Set fallbackLocale when creating i18n:
- string: fallbackLocale: 'en'
- array: fallbackLocale: ['en','fr']
- decision map: fallbackLocale: { 'de-CH': ['fr','it'], default: ['en','da'] }
Example: createI18n({ locale: 'ja', fallbackLocale: 'en', messages }) will use 'en' for missing keys. [1]
-
Implicit locale fallback: locales with region/dialect fall back automatically (e.g. de-DE-bavarian → de-DE → de). Append "!" to suppress implicit fallback (e.g. de-DE!). [1]
-
Defaults and warnings:
- fallbackLocale default is false (no explicit fallback). [2]
- By default fallback emits console warnings in dev; suppress with fallbackWarn / silentFallbackWarn and missingWarn / silentTranslationWarn depending on Composition vs Legacy API. [1]
-
Nuxt integration: pass fallbackLocale inside vueI18n options (supports same string/array/map shapes). [3]
Sources: Vue I18n fallback guide [1], Vue I18n API (fallbackLocale default) [2], Nuxt i18n docs (vueI18n options) [3].
Empty translations ("") across 76 keys will display as blank in Vietnamese UI
This file contains 76 empty-string values with no corresponding English fallback configured. Vue-i18n treats empty strings as valid translations by default and will not fall back to another locale when empty. This means Vietnamese users will see blank/missing labels for:
- New feature keys (
allow-dev-builds,allow-device,allow-prod-builds) - Channel management helpers (
channel-allow-device-self,channel-created,channel-disable-auto-update*) - Password requirements (
characters,characters-minimum) - Password policy settings (
password-policy,password-policy-description,password-policy-impact-warning,password-policy-required*) - Notification descriptions and webhook delivery helpers
Given the security sensitivity of password-policy and 2FA flows, consider either:
- Removing untranslated keys from
vi.jsonuntil real translations are ready, or - Seeding them with English strings as temporary placeholders and tracking missing translations separately
🤖 Prompt for AI Agents
In messages/vi.json around lines 174 to 182, there are empty-string translations
(and a total of 76 keys) which will render blank in the Vietnamese UI; find all
keys with "" values and either remove those keys from vi.json until a proper
Vietnamese translation exists or populate them with the English source text as
temporary placeholders, and add a short comment or entry in your translation
tracking (e.g., a missing-translations list or ticket) so they can be replaced
with proper Vietnamese translations later.
* feat: add 2FA enforcement fail card Implement 2FA enforcement UI when users don't have 2FA enabled but their organization requires it. Shows a fail card similar to password policy enforcement with a "Setup 2FA Now" button that auto-triggers the 2FA setup flow. Prevents data loading and displays enforcement message across dashboard, apps list, and organization settings pages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix: sort imports alphabetically in settings.vue 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add 2FA setup messages in multiple languages Added new translations for 2FA setup access and requirement messages in German, Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Turkish, Vietnamese, and Chinese. This enhances user experience by providing clear instructions for enabling 2FA across different languages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>



Summary (AI generated)
Implement 2FA enforcement UI messaging when users don't have 2FA enabled but their organization requires it. Shows a fail card similar to password policy enforcement with "Setup 2FA Now" button that auto-triggers the 2FA setup flow. Prevents unnecessary data loading when access is denied.
Test plan (AI generated)
Checklist (AI generated)
Motivation
I want to improve the frontend as the current implementation differs from the implementation described in #1291. I believe that 2FA enforcement is an imporant feautre and fixing the frontend is important for it to work properly.
Business impact
4/9 - Lowly Medium - The dashboard is the place where people interact with Capgo, so if 2FA enforcement doesn't work and doesn't show a clear error users will not understand capgo and they will become frustrated. This could lead to missed saled.
Changes (Human generated)
Before
After
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.