Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-2870]feat: language support #6215

Open
wants to merge 20 commits into
base: preview
Choose a base branch
from
Open

Conversation

mathalav55
Copy link
Collaborator

@mathalav55 mathalav55 commented Dec 17, 2024

Description

Added option to switch languages.
Added French, Spanish, and Japanese as supported languages.
Added language support for sidebar and user settings.

Type of Change

  • Feature (non-breaking change which adds functionality)

References

WEB-2870

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced internationalization support across various components, enabling dynamic translation of user-facing text.
    • Added new JSON translation files for English, Spanish, French, and Japanese languages.
    • Implemented a TranslationProvider to manage language context throughout the application.
    • Enhanced user profile management with a new language preference property.
    • Expanded profile-related navigation options with new tabs for "Summary," "Assigned," "Subscribed," and "Activity."
    • Added new entries for active cycles insights, providing detailed functionalities for monitoring and managing cycles.
  • Bug Fixes

    • Updated error and success messages to utilize translation functions, improving user feedback.
  • Chores

    • Added @plane/i18n dependency to the project for internationalization capabilities.
    • Updated next.config.js to include package transpilation settings.

Copy link
Contributor

coderabbitai bot commented Dec 17, 2024

Walkthrough

This pull request introduces a comprehensive internationalization (i18n) framework for the Plane application. The changes span multiple packages and components, establishing a robust translation system using the newly created @plane/i18n package. Key modifications include adding translation files for multiple languages (English, Spanish, French, Japanese), creating translation hooks and contexts, and integrating translation capabilities across various components and pages.

Changes

File Change Summary
packages/constants/src/workspace.ts Added TODO comment for translation in ORGANIZATION_SIZE
packages/i18n/ New package created with configuration files, translation hooks, and localization resources
packages/types/src/users.d.ts Added language property to user profile, removed role property
web/ Widespread integration of translation hooks in components and pages

Possibly related PRs

Suggested labels

⚙️backend, 🌟enhancement, 🔄migrations

Suggested reviewers

  • sriramveeraghanta
  • SatishGandham

Poem

🐰 A Translation Tale

In code's vast realm, words take flight,
From English, Spanish, day and night.
With hooks and contexts, languages dance,
A rabbit's dream of global expanse! 🌍
Translations bloom, no language barred. 🌈


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 26

🔭 Outside diff range comments (6)
web/core/components/workspace/sidebar/help-section.tsx (1)

Line range hint 153-153: Add missing translations

Some text strings remain untranslated:

  • "Discord" in the Discord community link
  • "Expand"/"Hide" in the sidebar toggle tooltip

Consider translating these strings for complete internationalization support.

- <span className="text-xs">Discord</span>
+ <span className="text-xs">{t("discord_community")}</span>

- <Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`} isMobile={isMobile}>
+ <Tooltip tooltipContent={`${isCollapsed ? t("expand") : t("hide")}`} isMobile={isMobile}>

Also applies to: 171-171

web/next.config.js (2)

Line range hint 89-103: Improve URL construction for god-mode routing

The current URL construction using string concatenation (ADMIN_BASE_URL + ADMIN_BASE_PATH) could lead to issues if the environment variables contain trailing or leading slashes. Consider using URL manipulation utilities to ensure proper URL formation.

Here's a suggested improvement:

-      const GOD_MODE_BASE_URL = ADMIN_BASE_URL + ADMIN_BASE_PATH;
+      const GOD_MODE_BASE_URL = new URL(ADMIN_BASE_PATH, ADMIN_BASE_URL).toString().replace(/\/$/, '');

Also, consider adding validation for the environment variables to ensure they contain valid URL components.


Security headers removal requires attention - potential security risk

The SECURITY.md explicitly states that "Missing [...] CSP headers" are out of scope, but makes no mention of the commented-out security headers (Referrer-Policy, COOP, COEP). These headers are important security controls:

  • Referrer-Policy: Controls how much referrer information is sent in requests
  • Cross-Origin-Opener-Policy (COOP): Isolates window references to prevent attacks
  • Cross-Origin-Embedder-Policy (COEP): Controls which resources can be loaded cross-origin

Since:

  1. There's no documentation justifying their removal
  2. These headers aren't implemented elsewhere in the codebase
  3. They're not listed as out-of-scope in SECURITY.md
  4. Their removal could impact the security posture

Please restore these security headers unless there's a specific technical requirement preventing their use. If they must remain disabled, document the reasoning and any compensating controls.

[security]

🔗 Analysis chain

Line range hint 15-21: Security headers have been commented out - please verify if this is intentional

Several important security headers have been commented out:

  • Referrer-Policy
  • Cross-Origin-Opener-Policy
  • Cross-Origin-Embedder-Policy

These headers help protect against various security vulnerabilities. Please verify if removing these headers is intentional and doesn't compromise security.


Let me check the content of SECURITY.md to see if it provides any context about these headers.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if these headers are defined elsewhere in the codebase
# or if there's any documentation explaining their removal

# Search for these headers in other configuration files
echo "Searching for security headers in other files..."
rg -i "referrer-policy|cross-origin-opener-policy|cross-origin-embedder-policy" --type yaml --type js

# Check for security-related documentation
echo "Checking for security documentation..."
fd -e md -e txt -H "security|headers" 

Length of output: 598


Script:

#!/bin/bash
# Check the content of SECURITY.md
cat SECURITY.md

# Also check for any recent commits or PRs that might have commented out these headers
git log -p --grep="header" web/next.config.js

Length of output: 3357

web/core/constants/profile.ts (2)

Line range hint 51-55: Replace hardcoded label with translation key

The label "Summary" should be internationalized to support multiple languages as per the PR objectives.

Replace the hardcoded string with a translation key:

   {
     key: "summary",
     route: "",
-    label: "Summary",
+    label: "profile.tabs.summary",
     selected: "/",
   },

Based on the investigation of the codebase, I can now provide a final response:

Translation keys need to be added to the i18n system

The review comment is correct about internationalizing the labels, but the suggested translation keys don't exist yet. The translation file at packages/i18n/src/locales/en/translations.json shows that:

  1. The i18n system is properly set up with support for multiple languages
  2. The file already contains some profile-related translations but doesn't have the specific tab labels yet
  3. The translation pattern used in the project is flat keys (not nested)

You'll need to:

  1. Add these translations to packages/i18n/src/locales/en/translations.json:
{
  "profile_tab_assigned": "Assigned",
  "profile_tab_created": "Created",
  "profile_tab_subscribed": "Subscribed",
  "profile_tab_activity": "Activity"
}
  1. Update the code to use these keys:
   {
     key: "assigned",
     route: "assigned",
-    label: "Assigned",
+    label: "profile_tab_assigned",
     selected: "/assigned/",
   },
   {
     route: "created",
-    label: "Created",
+    label: "profile_tab_created",
     selected: "/created/",
   },
   {
     key: "subscribed",
     route: "subscribed",
-    label: "Subscribed",
+    label: "profile_tab_subscribed",
     selected: "/subscribed/",
   },
   {
     key: "activity",
     route: "activity",
-    label: "Activity",
+    label: "profile_tab_activity",
     selected: "/activity/",
   },
🔗 Analysis chain

Line range hint 60-80: Internationalize tab labels for multi-language support

The labels "Assigned", "Subscribed", and "Activity" need to be internationalized to support French, Spanish, and Japanese as specified in the PR objectives.

Apply these changes to support multiple languages:

   {
     key: "assigned",
     route: "assigned",
-    label: "Assigned",
+    label: "profile.tabs.assigned",
     selected: "/assigned/",
   },
   {
     route: "created",
-    label: "Created",
+    label: "profile.tabs.created",
     selected: "/created/",
   },
   {
     key: "subscribed",
     route: "subscribed",
-    label: "Subscribed",
+    label: "profile.tabs.subscribed",
     selected: "/subscribed/",
   },
   {
     key: "activity",
     route: "activity",
-    label: "Activity",
+    label: "profile.tabs.activity",
     selected: "/activity/",
   },

Let's verify if translation keys are defined in the translation files:


The previous search might have failed because we didn't know the exact location or format of translation files. This script will help us locate translation-related files and understand the project structure better.


This will help us verify if the translation keys already exist and if the file is set up to use translations.


This will help us understand the translation structure and patterns used in the project.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the translation keys in the translation files
rg "profile\.tabs\." -A 1

Length of output: 27


Script:

#!/bin/bash
# Let's first check if there are any translation files in the repository
fd -e json -e yaml -e yml "translation|locale|i18n|lang"

# Also check for common translation file patterns
fd "en\.json|fr\.json|es\.json|ja\.json"

# Let's also check the directory structure to understand the project organization
fd -t d . -d 2

Length of output: 940


Script:

#!/bin/bash
# Let's check the content of the English translation file to see if these keys exist
cat packages/i18n/src/locales/en/translations.json | jq '.profile.tabs // empty'

# Let's also verify if the component is using the translation system
rg -A 2 "useTranslation|Trans|Translation" "web/core/constants/profile.ts"

# Check if there are any existing translation patterns in the profile.ts file
rg "\.t\(|i18n\." "web/core/constants/profile.ts"

Length of output: 274


Script:

#!/bin/bash
# Let's examine the actual content of the English translation file
cat packages/i18n/src/locales/en/translations.json

# Let's also check how translations are used in other parts of the web application
rg -A 2 "useTranslation|Trans|Translation" "web/core/"

# Check for any existing translation keys in the profile section
rg "profile\." "packages/i18n/src/locales/en/translations.json"

Length of output: 66323

web/app/profile/activity/page.tsx (1)

Line range hint 52-52: Add translation support for page title

The PageHead title is still hardcoded. Consider using the translation function for consistency.

- <PageHead title="Profile - Activity" />
+ <PageHead title={`${t("profile")} - ${t("activity")}`} />
🧹 Nitpick comments (60)
web/core/components/workspace/sidebar/dropdown.tsx (3)

33-51: Consider adding type safety for translation keys

The translation integration looks good, with proper useMemo optimization. However, consider using a type-safe approach for translation keys to prevent potential runtime errors.

// Consider adding a type for translation keys
type TranslationKey = 'workspace_invites' | 'workspace_settings' | /* other keys */;

// Then use it in the t function
const t = useTranslation<TranslationKey>();

129-129: Consider consolidating duplicate translations

The UI text translations are properly implemented, but there are duplicate translation keys for "sign_out" (lines 259 and 314). Consider using a constant for frequently used translation keys to maintain consistency and ease maintenance.

// At the top of the component
const TRANSLATIONS = {
  SIGN_OUT: 'sign_out',
  // other common translations...
} as const;

// Then use it consistently
{t(TRANSLATIONS.SIGN_OUT)}

Also applies to: 185-185, 225-225, 259-259, 301-301, 314-314, 322-322


Line range hint 32-322: Consider implementing a translation loading state

While the translations are well-implemented, consider adding a loading state for translations to prevent potential flash of untranslated content (FOUC) when the translations are being loaded. This could be particularly important for users with slower connections.

Consider implementing a translation loading wrapper:

const TranslationLoader: FC<{ children: ReactNode }> = ({ children }) => {
  const { ready } = useTranslation();
  if (!ready) return <LoadingSpinner />;
  return <>{children}</>;
};
web/core/components/workspace/create-workspace-form.tsx (4)

39-47: Consider adding type safety for translation keys

While the translation implementation is correct, consider creating a type-safe approach for translation keys to prevent potential runtime errors from typos or missing translations.

// Create a type for your translation keys
type WorkspaceTranslationKey = 
  | "creating_workspace"
  | "create_workspace"
  // ... other keys

// Use it in the component
const { t } = useTranslation<WorkspaceTranslationKey>();

Line range hint 81-103: Consider centralizing error handling logic

The error handling is scattered across multiple catch blocks with similar toast notifications. Consider extracting this into a reusable function.

const handleWorkspaceError = (eventElement: string) => {
  captureWorkspaceEvent({
    eventName: WORKSPACE_CREATED,
    payload: {
      state: "FAILED",
      element: t(eventElement),
    },
  });
  setToast({
    type: TOAST_TYPE.ERROR,
    title: t("error"),
    message: t("workspace_could_not_be_created_please_try_again"),
  });
};

Line range hint 191-198: Extract URL validation logic into a reusable utility

The URL validation logic is currently embedded in the onChange handler. Consider extracting it into a reusable utility function for better maintainability and potential reuse across the application.

// utils/validation.ts
export const isValidWorkspaceUrl = (url: string): boolean => /^[a-zA-Z0-9_-]+$/.test(url);

// In component
onChange={(e) => {
  const newValue = e.target.value.toLowerCase();
  setInvalidSlug(!isValidWorkspaceUrl(newValue));
  onChange(newValue);
}}

138-144: Extract validation constants

Consider extracting the validation rules' magic numbers into named constants for better maintainability and documentation.

const WORKSPACE_VALIDATION = {
  NAME_MAX_LENGTH: 80,
  SLUG_MAX_LENGTH: 48,
  NAME_PATTERN: /^[\w\s-]*$/,
} as const;

// Use in validation rules
maxLength: {
  value: WORKSPACE_VALIDATION.NAME_MAX_LENGTH,
  message: t("limit_your_name_to_80_characters"),
}
web/app/profile/appearance/page.tsx (1)

64-64: Consider translating the page title

The page title "Profile - Appearance" is still hardcoded. Consider using the translation function for consistency with the rest of the internationalized content.

-<PageHead title="Profile - Appearance" />
+<PageHead title={`${t("profile")} - ${t("appearance")}`} />
web/core/components/workspace/sidebar/help-section.tsx (2)

99-99: Maintain consistent translation key naming convention

The translation key message_support uses snake_case while other keys use different conventions. Consider standardizing the naming convention across all translation keys for better maintainability.


144-144: Consider standardizing special character handling in translation keys

The translation key whats_new is missing an apostrophe. Consider establishing guidelines for handling special characters in translation keys for consistency.

web/core/components/global/product-updates/modal.tsx (1)

31-41: Add type safety and fallback handling for translations

Consider implementing type safety for translation keys and adding fallback handling for missing translations to improve reliability.

Example implementation:

// Define translation key types
type ProductUpdatesTranslationKeys = {
  'product_updates.error.fetch_failed': string;
  'product_updates.changelog.visit_prefix': string;
  'product_updates.changelog.link_text': string;
  'product_updates.changelog.visit_suffix': string;
};

// Use with fallback
const { t } = useTranslation<ProductUpdatesTranslationKeys>();
t('product_updates.error.fetch_failed', 'Unable to fetch updates') // With fallback
web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (2)

47-48: Consider using namespaced translation keys.

While the translations are correctly implemented, consider using namespaced keys to avoid potential conflicts and improve maintainability. For example:

  • errorcommon.error
  • folder_already_existsfavorites.folder.errors.already_exists
-        title: t("error"),
-        message: t("folder_already_exists"),
+        title: t("common.error"),
+        message: t("favorites.folder.errors.already_exists"),

Also applies to: 61-62, 69-70, 76-77


137-137: Consider adding aria-label for better accessibility.

The input field could benefit from an aria-label to improve accessibility for screen readers.

-          render={({ field }) => <Input className="w-full" placeholder={t("new_folder")} {...field} />}
+          render={({ field }) => (
+            <Input
+              className="w-full"
+              placeholder={t("new_folder")}
+              aria-label={t("new_folder")}
+              {...field}
+            />
+          )}
web/ce/components/projects/create/attributes.tsx (2)

46-46: Consider translating network options

While the placeholder is correctly translated, consider also translating the network labels and descriptions from NETWORK_CHOICES.

Example implementation:

<CustomSelect.Option key={network.key} value={network.key}>
  <div className="flex items-start gap-2">
    <network.icon className="h-3.5 w-3.5" />
    <div className="-mt-1">
-     <p>{network.label}</p>
-     <p className="text-xs text-custom-text-400">{network.description}</p>
+     <p>{t(`network.${network.key}.label`)}</p>
+     <p className="text-xs text-custom-text-400">{t(`network.${network.key}.description`)}</p>
    </div>
  </div>
</CustomSelect.Option>

82-82: Consider using a more descriptive translation key

The translation key "lead" is quite generic and could lead to naming conflicts. Consider using a more specific key that includes the context.

-placeholder={t("lead")}
+placeholder={t("project.create.lead_placeholder")}
web/core/constants/profile.ts (1)

Line range hint 1-82: Consider adding type safety for translation keys

To ensure type safety and prevent typos in translation keys, consider defining an interface or type for the translation keys.

Add a type definition at the top of the file:

type ProfileTabTranslationKey =
  | "profile.tabs.summary"
  | "profile.tabs.assigned"
  | "profile.tabs.created"
  | "profile.tabs.subscribed"
  | "profile.tabs.activity";

interface ProfileTab {
  key: string;
  route: string;
  label: ProfileTabTranslationKey;
  selected: string;
}
web/core/components/workspace/sidebar/workspace-menu.tsx (2)

10-10: Add fallback handling for translations

While the translation implementation is good, we should add fallback handling for missing translations to prevent potential runtime issues.

- <span>{t("workspace").toUpperCase()}</span>
+ <span>{(t("workspace") || "Workspace").toUpperCase()}</span>

- <span>{t("archives")}</span>
+ <span>{t("archives") || "Archives"}</span>

- <span>{t("settings")}</span>
+ <span>{t("settings") || "Settings"}</span>

Also applies to: 41-41, 89-89, 116-116, 126-126


166-166: Optimize rendering performance

The menu item rendering logic can be optimized to prevent unnecessary re-renders and improve performance:

  1. Memoize the translation function calls
  2. Extract the menu item component for better re-render control
+ const MenuItemComponent = React.memo(({ link, sidebarCollapsed, t }) => {
+   const translatedLabel = React.useMemo(() => t(link.key), [t, link.key]);
+   return (
      <SidebarNavItem
        key={link.value}
        className={`${sidebarCollapsed ? "p-0 size-8 aspect-square justify-center mx-auto" : ""}`}
        isActive={link.highlight(pathname, `/${workspaceSlug}`)}
      >
        <div className="flex items-center gap-1.5 py-[1px]">
          <link.Icon
            className={cn("size-4", {
              "rotate-180": link.value === "active-cycles",
            })}
          />
-         {!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{t(link.key)}</p>}
+         {!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{translatedLabel}</p>}
        </div>
        {!sidebarCollapsed && link.value === "active-cycles" && indicatorElement}
      </SidebarNavItem>
+   );
+ });

Also applies to: 170-171, 177-177, 179-179, 189-189, 191-191

web/ce/components/global/version-number.tsx (1)

2-2: Consider adding type safety for translation keys.

While the implementation works, consider using a type-safe approach for translation keys to catch potential typos or missing translations at compile time.

- const { t } = useTranslation();
- return <span>{t("version")}: v{packageJson.version}</span>;
+ type TranslationKey = "version";  // Define allowed keys
+ const { t } = useTranslation<TranslationKey>();
+ return <span>{t("version", "Version")}: v{packageJson.version}</span>;  // Add fallback

Also applies to: 6-7

packages/i18n/src/config/index.ts (1)

22-39: Internationalize language labels.

The language labels themselves should be translatable to provide a fully localized experience.

export const SUPPORTED_LANGUAGES = [
  {
-   label: "English",
+   labelKey: "language_english",  // Add these keys to translation files
    value: "en",
  },
  {
-   label: "French",
+   labelKey: "language_french",
    value: "fr",
  },
  // ... similar changes for other languages
];
packages/i18n/src/components/index.tsx (1)

7-7: Consider making translationStore configurable.

The translationStore is created as a singleton, which might make testing and configuration difficult.

-const translationStore = new TranslationStore();
+export const createTranslationStore = (config?: TranslationConfig) => new TranslationStore(config);
+const defaultTranslationStore = createTranslationStore();

-export const TranslationContext = createContext<TranslationStore>(translationStore);
+export const TranslationContext = createContext<TranslationStore>(defaultTranslationStore);

-export const TranslationProvider = observer(({ children }: { children: React.ReactNode }) => {
+export const TranslationProvider = observer(({
+  children,
+  store = defaultTranslationStore
+}: {
+  children: React.ReactNode;
+  store?: TranslationStore;
+}) => {
web/core/components/project/create/project-create-buttons.tsx (1)

2-2: Consider using namespaced and type-safe translation keys.

While the translation implementation works, consider these improvements for better maintainability:

  1. Use namespaced keys (e.g., "project.create.button.cancel") to avoid key conflicts
  2. Add type safety for translation keys to catch missing translations at compile time

Example implementation:

// types/i18n.ts
export const PROJECT_TRANSLATIONS = {
  create: {
    button: {
      cancel: 'cancel',
      create: 'create_project',
      creating: 'creating'
    }
  }
} as const;

type TranslationKeys = typeof PROJECT_TRANSLATIONS;

Also applies to: 17-17, 28-28, 31-31

packages/i18n/src/components/store.ts (1)

1-38: Add type safety and validation for translations.

Consider adding:

  1. Type-safe translation keys
  2. Runtime validation of translation completeness
  3. Unit tests for the translation store

Create a translation validator:

type TranslationSchema = Record<string, string>;

function validateTranslations(translations: Record<Language, TranslationSchema>) {
  const baseKeys = Object.keys(translations[fallbackLng]);
  
  for (const lang of languages) {
    const missingKeys = baseKeys.filter(
      key => !translations[lang][key]
    );
    
    if (missingKeys.length > 0) {
      console.warn(`Missing translations in ${lang}:`, missingKeys);
    }
  }
}
web/app/profile/notifications/page.tsx (1)

28-32: Consider breaking down long translation key

The translation key stay_in_the_loop_on_issues_you_are_subscribed_to_enable_this_to_get_notified is quite long. Consider breaking it into smaller, more manageable segments or using a shorter key name for better maintainability.

-description={t("stay_in_the_loop_on_issues_you_are_subscribed_to_enable_this_to_get_notified")}
+description={t("notification_settings.subscription_description")}
web/core/constants/themes.ts (1)

4-4: Consider internationalizing theme labels

While adding the key property is good for unique identification, consider also internationalizing the theme labels for consistent language support across the application.

 {
   key: "system_preference",
   value: "system",
-  label: "System preference",
+  label: t("themes.system_preference"),
   type: "light",
   // ... rest of the properties
 }

This would require:

  1. Moving the theme options to a component or hook where useTranslation is available
  2. Adding corresponding translation keys to the i18n files

Also applies to: 17-17, 28-28, 39-39, 50-50, 61-61, 72-72

web/core/components/global/product-updates/footer.tsx (1)

Line range hint 15-50: Consider extracting URLs to constants.

The hardcoded URLs should be moved to a constants file for better maintainability.

Create a new file constants/external-links.ts:

export const EXTERNAL_LINKS = {
  DOCS: "https://go.plane.so/p-docs",
  CHANGELOG: "https://go.plane.so/p-changelog",
  SUPPORT_EMAIL: "mailto:[email protected]",
  DISCORD: "https://go.plane.so/p-discord",
  PLANE_PAGES: "https://plane.so/pages"
} as const;

Then update the component to use these constants:

-       href="https://go.plane.so/p-docs"
+       href={EXTERNAL_LINKS.DOCS}
web/core/components/core/theme/theme-switch.tsx (1)

76-76: Consider adding fallback text

Consider adding fallback text when translations are missing to ensure graceful degradation.

-            {t(themeOption.key)}
+            {t(themeOption.key) || themeOption.label}
web/core/components/account/password-strength-meter.tsx (1)

62-62: Optimize strengthBars memoization

The t function in the dependency array might cause unnecessary re-renders as it could change on every render. Consider wrapping the component with React.memo or moving the translation logic outside the memoization.

-  }, [strength,t]);
+  }, [strength]);
web/ce/constants/project/settings/features.tsx (2)

7-7: Enhance type safety for translation keys

Consider creating a type-safe approach for translation keys to prevent typos and ensure all keys are defined in translation files.

type TranslationKey = keyof typeof translations; // Define in i18n package

export type TProperties = {
  key: TranslationKey; // Use strict type instead of string
  // ... other properties
};

Also applies to: 27-27


41-41: Maintain consistency between keys and properties

Some feature keys don't match their corresponding properties, which could lead to confusion. Consider aligning them for better maintainability.

Example for inbox feature:

-        key: "intake",
-        property: "inbox_view",
+        key: "inbox",
+        property: "inbox_view",

Also applies to: 50-50, 59-59, 68-68, 77-77

web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx (1)

38-39: Simplify translation keys

The current translation keys are quite verbose. Consider using shorter, hierarchical keys.

-            <h2 className="text-2xl font-semibold">{t("on_demand_snapshots_of_all_your_cycles")}</h2>
-            <p className="text-base font-medium text-custom-text-300">{t("active_cycles_description")}</p>
+            <h2 className="text-2xl font-semibold">{t("cycles.snapshots.title")}</h2>
+            <p className="text-base font-medium text-custom-text-300">{t("cycles.snapshots.description")}</p>
web/core/components/workspace/sidebar/user-menu.tsx (2)

72-73: Consider using distinct translation keys for tooltips and labels

Using the same translation key (link.key) for both tooltip and visible text might be limiting when different wording is needed for tooltips vs labels in some languages.

- tooltipContent={t(link.key)}
+ tooltipContent={t(`${link.key}_tooltip`)}

- {!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{t(link.key)}</p>}
+ {!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{t(`${link.key}_label`)}</p>}

Also applies to: 86-86, 88-88


26-26: Consider memoizing translation hook

The useTranslation hook at component level could cause unnecessary re-renders. Consider memoizing the translation function or moving it to a more specific component scope.

+ const memoizedT = React.useMemo(() => t, [t]);
web/core/components/project/create/header.tsx (2)

38-38: Consider using constant translation keys

Using hardcoded string literals for translation keys can lead to maintenance issues. Consider defining these in a constants file.

// constants/translations.ts
export const TRANSLATION_KEYS = {
  PROJECT: {
    COVER_IMAGE_ALT: 'project_cover_image_alt',
    CHANGE_COVER: 'change_cover'
  }
} as const;

// Usage in component
alt={t(TRANSLATION_KEYS.PROJECT.COVER_IMAGE_ALT)}

Also applies to: 53-53


25-25: Add translations for error states and aria labels

While basic text is translated, consider adding translations for error messages and accessibility attributes.

+ aria-label={t("project_cover_image_aria_label")}

Also applies to: 38-38, 53-53

web/app/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx (2)

84-84: Consider shorter, hierarchical translation keys

The current translation key is very long. Consider using a more structured, hierarchical approach for better maintainability.

- {t("you_do_not_have_the_permission_to_access_this_page")}
+ {t("errors.permissions.page_access_denied")}

36-36: Add translations for loading and error states

While the permission error is translated, consider adding translations for loading states and other potential error conditions.

// Add translations for loading and error states
{isLoading ? (
  <div>{t("common.loading")}</div>
) : error ? (
  <div>{t("errors.generic")}</div>
) : (
  // ... existing content
)}

Also applies to: 84-84

web/core/components/workspace/sidebar/quick-actions.tsx (1)

97-97: Consider adding aria-label for accessibility

While the translation is correctly implemented, consider adding an aria-label to the button to ensure screen readers announce the translated text correctly.

- {!isSidebarCollapsed && <span className="text-sm font-medium">{t("new_issue")}</span>}
+ {!isSidebarCollapsed && <span className="text-sm font-medium" aria-label={t("new_issue")}>{t("new_issue")}</span>}
web/core/components/project/create/common-attributes.tsx (1)

84-85: Consider updating the project identifier validation regex

The regex pattern /^[ÇŞĞIİÖÜA-Z0-9]+$/ includes specific non-Latin characters. Consider using Unicode properties for a more comprehensive solution that supports all languages.

-/^[ÇŞĞIİÖÜA-Z0-9]+$/.test(value.toUpperCase())
+/^[\p{L}\p{N}]+$/u.test(value.toUpperCase())
packages/types/src/users.d.ts (1)

64-64: Consider using a more specific type for language field

Instead of using a broad string type, consider using a union type of supported language codes for better type safety.

-language: string;
+language: "en" | "fr" | "es" | "ja";
web/core/components/workspace/sidebar/project-navigation.tsx (1)

149-149: Consider handling missing translations

While the translation implementation is correct, consider adding a fallback mechanism for missing translations to prevent displaying raw translation keys to users.

-            tooltipContent={`${project?.name}: ${t(item.key)}`}
+            tooltipContent={`${project?.name}: ${t(item.key, { fallback: item.name })}`}

-            {!isSidebarCollapsed && <span className="text-xs font-medium">{t(item.key)}</span>}
+            {!isSidebarCollapsed && <span className="text-xs font-medium">{t(item.key, { fallback: item.name })}</span>}

Also applies to: 163-163

web/core/components/profile/notification/email-notification-form.tsx (1)

38-40: Consider centralizing toast message translations

While the translation of toast messages is correct, consider creating a dedicated translation namespace for toast messages to maintain consistency across the application.

-        title: t("success"),
-        message: t("email_notification_setting_updated_successfully"),
+        title: t("toast.success"),
+        message: t("toast.email_notification_setting_updated_successfully"),

-        title: t("error"),
-        message: t("failed_to_update_email_notification_setting"),
+        title: t("toast.error"),
+        message: t("toast.failed_to_update_email_notification_setting"),

Also applies to: 45-47

web/app/profile/security/page.tsx (1)

82-91: Consider translating error messages from authErrorHandler

The error messages from authErrorHandler might not be translated. Consider wrapping these messages with the translation function to ensure consistent internationalization.

- const errorInfo = authErrorHandler(err.error_code?.toString());
+ const errorInfo = {
+   ...authErrorHandler(err.error_code?.toString()),
+   message: t(authErrorHandler(err.error_code?.toString()).message)
+ };
web/core/components/core/theme/custom-theme-selector.tsx (1)

41-57: Consider extracting validation messages to constants

The validation messages are repeated multiple times in the inputRules object. Consider extracting these to constants to improve maintainability.

+ const VALIDATION_MESSAGES = {
+   HEX_CODE: 'enter_a_valid_hex_code_of_6_characters'
+ };

const inputRules = useMemo(
  () => ({
    minLength: {
      value: 7,
-     message: t("enter_a_valid_hex_code_of_6_characters"),
+     message: t(VALIDATION_MESSAGES.HEX_CODE),
    },
    // ... apply to other rules
  }),
  [t]
);
web/app/invitations/page.tsx (1)

76-77: Maintain consistent error message structure

The error messages are repeated in multiple catch blocks. Consider extracting these to a constant to maintain consistency and ease maintenance.

+ const ERROR_MESSAGES = {
+   TITLE: 'error',
+   DEFAULT: 'something_went_wrong_please_try_again',
+   SELECTION: 'please_select_at_least_one_invitation'
+ };

- title: t("error"),
- message: t("something_went_wrong_please_try_again"),
+ title: t(ERROR_MESSAGES.TITLE),
+ message: t(ERROR_MESSAGES.DEFAULT),

Also applies to: 111-112, 126-127

web/app/profile/sidebar.tsx (2)

95-96: Consider using more specific error translation keys.

The generic error message keys could be more specific to the sign-out context for better maintainability.

-          title: t("error"),
-          message: t("failed_to_sign_out_please_try_again"),
+          title: t("sign_out_error"),
+          message: t("sign_out_failed_please_try_again"),

136-136: Ensure translation key consistency.

The translation key pattern varies between different components. Consider standardizing the key format:

  • Some keys use snake_case: create_workspace
  • Others use full sentences: failed_to_sign_out_please_try_again

Also applies to: 149-149

web/core/components/workspace/sidebar/projects-list.tsx (1)

89-90: Use context-specific error translation keys.

The error messages could be more specific to the project reordering context.

-          title: t("error"),
-          message: t("something_went_wrong"),
+          title: t("project_error"),
+          message: t("project_reorder_failed"),
web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (2)

70-71: Standardize error translation keys across favorite operations.

Multiple error scenarios use generic error messages. Consider using operation-specific translation keys for better maintainability and clarity.

// For moving favorites
-          title: t("error"),
-          message: t("failed_to_move_favorite"),
+          title: t("favorite_error"),
+          message: t("favorite_move_failed"),

// For general errors
-          title: t("error"),
-          message: t("something_went_wrong"),
+          title: t("favorite_error"),
+          message: t("favorite_operation_failed"),

// For reordering
-          title: t("error"),
-          message: t("failed_to_reorder_favorite"),
+          title: t("favorite_error"),
+          message: t("favorite_reorder_failed"),

Also applies to: 128-129, 137-138, 148-149


245-247: Consider using a more semantic translation key for empty state.

The empty state message could use a more descriptive translation key.

-                      {t("no_favorites_yet")}
+                      {t("favorites_empty_state_message")}
packages/i18n/src/locales/ja/translations.json (1)

46-47: Consider localizing "workspace" term

The term "workspace" is left in English. Consider using a more localized term like "ワークスペース" consistently throughout the translations for better user experience.

-  "workspaces": "Workspaces",
-  "create_workspace": "Crear workspace",
+  "workspaces": "ワークスペース",
+  "create_workspace": "ワークスペースを作成",
packages/i18n/src/locales/es/translations.json (1)

46-47: Consider localizing "workspace" term

The term "workspace" is left in English. Consider using "espacio de trabajo" consistently throughout the translations.

-  "workspaces": "Workspaces",
-  "create_workspace": "Crear workspace",
+  "workspaces": "Espacios de trabajo",
+  "create_workspace": "Crear espacio de trabajo",
web/core/components/workspace/sidebar/projects-list-item.tsx (3)

93-100: Consider adding type safety for translation keys

While the translation implementation is correct, consider enhancing type safety for translation keys to prevent potential runtime errors and improve maintainability.

Consider using a TypeScript enum or const object for translation keys:

// i18n/constants.ts
export const TOAST_MESSAGES = {
  ADDING_TO_FAVORITES: "adding_project_to_favorites",
  REMOVING_FROM_FAVORITES: "removing_project_from_favorites",
  SUCCESS: "success",
  ERROR: "error",
} as const;

// Then in your component
t(TOAST_MESSAGES.ADDING_TO_FAVORITES)

Also applies to: 110-117


256-258: Extract tooltip logic for better maintainability

Consider extracting the tooltip content logic to improve readability and maintainability.

const getDragTooltipContent = (sortOrder: number | null) => {
  return sortOrder === null
    ? t("join_the_project_to_rearrange")
    : t("drag_to_rearrange");
};

// Then in JSX
tooltipContent={getDragTooltipContent(project.sort_order)}

Line range hint 366-376: Clean up commented code

There's a commented-out section for "Draft issues" that should either be removed or implemented with proper translations.

If this feature is planned for future implementation, consider adding a TODO comment with more context or create a tracking issue.

web/core/components/profile/form.tsx (5)

306-333: Align display_name length validation with maxLength property

There is a discrepancy between the validation logic and the maxLength property for the display_name field. The validation restricts the length to less than 20 characters after removing spaces, while the maxLength attribute allows up to 24 characters. This inconsistency may confuse users.

Consider updating the maxLength to 20 to match the validation rules or adjust the validation to allow up to 24 characters.

Apply this diff to align the maxLength with the validation:

-                          maxLength={24}
+                          maxLength={20}

Alternatively, adjust the validation rule:

-                          if (value.replace(/\s/g, "").length > 20)
+                          if (value.replace(/\s/g, "").length > 24)

346-362: Update placeholder text for disabled email field

The email input field is disabled but contains the placeholder "Enter your email," which might confuse users since they cannot edit it.

Consider changing the placeholder to "Email" or removing it to prevent confusion.

Apply this diff to update the placeholder text:

-                          placeholder="Enter your email"
+                          placeholder="Email"

209-214: Improve accessibility by avoiding onClick on <img> elements

Using onClick directly on an <img> element can cause accessibility issues, as images are not inherently interactive and may not be focusable or accessible via keyboard navigation.

Wrap the <img> element within a <button> to enhance accessibility and semantic correctness.

Apply this diff to refactor the clickable image:

-                            <img
-                              src={getFileURL(userAvatar)}
-                              className="absolute left-0 top-0 h-full w-full rounded-lg object-cover"
-                              onClick={() => setIsImageUploadModalOpen(true)}
-                              alt={currentUser?.display_name}
-                              role="button"
-                            />
+                            <button
+                              type="button"
+                              className="absolute left-0 top-0 h-full w-full rounded-lg overflow-hidden"
+                              onClick={() => setIsImageUploadModalOpen(true)}
+                              aria-label="Edit profile picture"
+                            >
+                              <img
+                                src={getFileURL(userAvatar)}
+                                className="h-full w-full object-cover"
+                                alt={currentUser?.display_name}
+                              />
+                            </button>

247-274: Add length validation for first_name field

The first_name field has a maxLength attribute of 24 but lacks corresponding validation to enforce this limit. This could lead to inconsistent user experiences if users exceed the maximum length.

Introduce a maxLength validation rule to ensure the input does not exceed 24 characters.

Apply this diff to add length validation:

                      rules={{
                          required: "Please enter first name",
+                         maxLength: {
+                           value: 24,
+                           message: "First name cannot exceed 24 characters",
+                         },
                      }}

277-297: Add length validation for last_name field

Similarly, the last_name field lacks a validation rule to enforce the maxLength of 24 characters, which may result in inconsistent behavior.

Add a maxLength validation rule to the last_name field.

Apply this diff to include length validation:

                      rules={{
+                         maxLength: {
+                           value: 24,
+                           message: "Last name cannot exceed 24 characters",
+                         },
                      }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ede4aad and 07c5147.

📒 Files selected for processing (71)
  • packages/constants/src/workspace.ts (1 hunks)
  • packages/i18n/.eslintignore (1 hunks)
  • packages/i18n/.eslintrc.js (1 hunks)
  • packages/i18n/.prettierignore (1 hunks)
  • packages/i18n/.prettierrc (1 hunks)
  • packages/i18n/package.json (1 hunks)
  • packages/i18n/src/components/index.tsx (1 hunks)
  • packages/i18n/src/components/store.ts (1 hunks)
  • packages/i18n/src/config/index.ts (1 hunks)
  • packages/i18n/src/hooks/index.ts (1 hunks)
  • packages/i18n/src/hooks/use-translation.ts (1 hunks)
  • packages/i18n/src/index.ts (1 hunks)
  • packages/i18n/src/locales/en/translations.json (1 hunks)
  • packages/i18n/src/locales/es/translations.json (1 hunks)
  • packages/i18n/src/locales/fr/translations.json (1 hunks)
  • packages/i18n/src/locales/ja/translations.json (1 hunks)
  • packages/i18n/tsconfig.json (1 hunks)
  • packages/types/src/users.d.ts (1 hunks)
  • web/app/[workspaceSlug]/(projects)/active-cycles/header.tsx (2 hunks)
  • web/app/[workspaceSlug]/(projects)/analytics/header.tsx (3 hunks)
  • web/app/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx (3 hunks)
  • web/app/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx (3 hunks)
  • web/app/create-workspace/page.tsx (5 hunks)
  • web/app/invitations/page.tsx (8 hunks)
  • web/app/profile/activity/page.tsx (3 hunks)
  • web/app/profile/appearance/page.tsx (3 hunks)
  • web/app/profile/notifications/page.tsx (3 hunks)
  • web/app/profile/page.tsx (2 hunks)
  • web/app/profile/security/page.tsx (7 hunks)
  • web/app/profile/sidebar.tsx (11 hunks)
  • web/app/provider.tsx (2 hunks)
  • web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx (5 hunks)
  • web/ce/components/global/product-updates-header.tsx (1 hunks)
  • web/ce/components/global/version-number.tsx (1 hunks)
  • web/ce/components/projects/create/attributes.tsx (4 hunks)
  • web/ce/components/projects/create/root.tsx (5 hunks)
  • web/ce/components/workspace/edition-badge.tsx (3 hunks)
  • web/ce/constants/dashboard.ts (4 hunks)
  • web/ce/constants/project/settings/features.tsx (8 hunks)
  • web/core/components/account/password-strength-meter.tsx (2 hunks)
  • web/core/components/core/theme/custom-theme-selector.tsx (10 hunks)
  • web/core/components/core/theme/theme-switch.tsx (4 hunks)
  • web/core/components/global/product-updates/footer.tsx (2 hunks)
  • web/core/components/global/product-updates/modal.tsx (3 hunks)
  • web/core/components/profile/form.tsx (1 hunks)
  • web/core/components/profile/index.ts (1 hunks)
  • web/core/components/profile/notification/email-notification-form.tsx (8 hunks)
  • web/core/components/project/create/common-attributes.tsx (8 hunks)
  • web/core/components/project/create/header.tsx (4 hunks)
  • web/core/components/project/create/project-create-buttons.tsx (3 hunks)
  • web/core/components/project/form.tsx (3 hunks)
  • web/core/components/project/project-feature-update.tsx (3 hunks)
  • web/core/components/project/settings/features-list.tsx (4 hunks)
  • web/core/components/workspace/create-workspace-form.tsx (10 hunks)
  • web/core/components/workspace/sidebar/dropdown.tsx (10 hunks)
  • web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (7 hunks)
  • web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (7 hunks)
  • web/core/components/workspace/sidebar/help-section.tsx (8 hunks)
  • web/core/components/workspace/sidebar/project-navigation.tsx (11 hunks)
  • web/core/components/workspace/sidebar/projects-list-item.tsx (10 hunks)
  • web/core/components/workspace/sidebar/projects-list.tsx (6 hunks)
  • web/core/components/workspace/sidebar/quick-actions.tsx (3 hunks)
  • web/core/components/workspace/sidebar/user-menu.tsx (3 hunks)
  • web/core/components/workspace/sidebar/workspace-menu.tsx (6 hunks)
  • web/core/constants/cycle.ts (1 hunks)
  • web/core/constants/profile.ts (3 hunks)
  • web/core/constants/themes.ts (7 hunks)
  • web/core/lib/wrappers/store-wrapper.tsx (3 hunks)
  • web/core/store/user/profile.store.ts (1 hunks)
  • web/next.config.js (1 hunks)
  • web/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (12)
  • packages/i18n/.eslintignore
  • packages/i18n/.prettierrc
  • packages/i18n/.eslintrc.js
  • packages/constants/src/workspace.ts
  • packages/i18n/src/hooks/index.ts
  • packages/i18n/.prettierignore
  • packages/i18n/src/index.ts
  • packages/i18n/tsconfig.json
  • packages/i18n/package.json
  • web/core/components/profile/index.ts
  • packages/i18n/src/locales/en/translations.json
  • packages/i18n/src/locales/fr/translations.json
🧰 Additional context used
🪛 Biome (1.9.4)
web/core/components/workspace/sidebar/projects-list.tsx

[error] 186-192: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (56)
web/core/components/workspace/sidebar/dropdown.tsx (2)

3-3: LGTM! Proper integration of i18n imports

The imports are correctly organized, and the useTranslation hook is properly imported from the @plane/i18n package.

Also applies to: 13-13


94-95: LGTM! Proper error message translations

Error messages are correctly internationalized while maintaining the existing error handling structure.

web/app/profile/appearance/page.tsx (3)

6-6: LGTM: Import statement is correctly placed

The addition of the useTranslation hook import is appropriate for implementing internationalization support.


20-20: LGTM: Translation hook is properly initialized

The useTranslation hook is correctly implemented at the component level, following React hooks best practices.


66-70: Verify translation key existence and consistency

The translation keys are being used correctly, but let's verify that they exist in all language files to prevent runtime errors.

✅ Verification successful

Let me verify the actual content of these translation keys in the locale files.


Translation keys are properly implemented across all language files

All three translation keys ("appearance", "theme", and "select_or_customize_your_interface_color_scheme") are present and correctly translated in all language files (English, Spanish, French, and Japanese) under packages/i18n/src/locales/. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the translation keys exist in all language files

# Find all translation files
echo "Searching for translation files..."
fd -e json -e yaml -e yml . | grep -i "translation\|locale\|lang"

# Search for the specific keys being used
echo "Checking for translation keys..."
rg -l "appearance|theme|select_or_customize_your_interface_color_scheme" --type json --type yaml

Length of output: 897


Script:

#!/bin/bash
# Check the actual content of the translation keys in all locale files
for key in "appearance" "theme" "select_or_customize_your_interface_color_scheme"; do
  echo "Checking key: $key"
  echo "-------------------"
  rg "\"$key\"" packages/i18n/src/locales/*/translations.json
  echo -e "\n"
done

Length of output: 2537

web/core/components/workspace/sidebar/help-section.tsx (3)

7-7: LGTM: Clean import of translation hook

The addition of the useTranslation hook import aligns with the PR's internationalization objectives.


28-28: LGTM: Proper translation hook initialization

The useTranslation hook is correctly initialized at the component level, following React hooks best practices.


88-88: Verify translation key existence

The translation implementation looks correct, but we should verify the existence of the "documentation" key in the translation files.

✅ Verification successful

Translation key "documentation" is properly defined across locales

The "documentation" translation key is present in all translation files (en, es, fr, ja) with appropriate translations, confirming proper i18n implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the "documentation" translation key in all translation files
rg -g '*.{json,ts,js}' '"documentation"' 

Length of output: 367

web/core/components/global/product-updates/modal.tsx (2)

3-3: LGTM: Import statement is correctly placed

The addition of the useTranslation hook import is consistent with the internationalization objective and follows the existing import structure.


20-20: LGTM: Hook usage follows best practices

The useTranslation hook is correctly implemented at the component's top level, following React hooks best practices.

web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (3)

6-6: LGTM: Translation hook import added correctly.

The useTranslation hook is properly imported from the @plane/i18n package.


28-28: LGTM: Translation hook initialized correctly.

The useTranslation hook is properly initialized at the component level, following React hooks best practices.


137-137: Verify translation coverage for new_folder key.

The placeholder translation is correctly implemented. Let's verify that the "new_folder" translation key exists in all supported language files (French, Spanish, and Japanese).

✅ Verification successful

Translation key "new_folder" is properly defined in all supported languages

The translation key "new_folder" is present in all required language files (English, French, Spanish, and Japanese) with appropriate translations:

  • English: "New folder"
  • French: "Nouveau dossier"
  • Spanish: "Nueva carpeta"
  • Japanese: "新しいフォルダー"
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new_folder translation key exists in all language files

# Search for translation files and check for the new_folder key
fd -e json -e yaml -e yml . | xargs rg "new_folder"

Length of output: 365

web/next.config.js (1)

32-32: LGTM: Correct configuration for i18n support

The addition of @plane/i18n to transpilePackages is necessary for proper integration of the internationalization package.

web/ce/components/projects/create/attributes.tsx (3)

4-4: LGTM: Clean import of i18n hook

The import statement is properly placed and uses the correct package path.


22-22: LGTM: Proper hook initialization

The translation hook is correctly initialized at the component level, making the translation function available throughout the component.


4-4: Verify translation key definitions

Let's verify that all used translation keys are properly defined in the translation files.

Also applies to: 22-22, 46-46, 82-82

✅ Verification successful

Translation keys are properly defined and used

The translation keys "select_network" and "lead" used in web/ce/components/projects/create/attributes.tsx are correctly defined in the English translation file at packages/i18n/src/locales/en/translations.json. The implementation follows the established i18n patterns across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if translation keys are defined in all language files

# Find all translation files
echo "Searching for translation files..."
fd -e json -p "translations/"

# Search for the used translation keys
echo -e "\nChecking for translation keys..."
for key in "select_network" "lead"; do
  echo -e "\nSearching for key: $key"
  rg -l "\"$key\":" translations/
done

Length of output: 591


Script:

#!/bin/bash
# Let's first locate the translation files in the repository
echo "Searching for i18n or translation related files..."
fd -t f "i18n|translation|locale" --full-path

# Let's also check the imports of translation utilities
echo -e "\nChecking translation utility imports..."
rg "import.*@plane/i18n" -A 2

# Let's check the actual usage of useTranslation
echo -e "\nChecking useTranslation usage..."
ast-grep --pattern 'const { t } = useTranslation();'

Length of output: 16130


Script:

#!/bin/bash
# Let's check the translation files content
echo "Checking translation files content..."
cat packages/i18n/src/locales/en/translations.json

# Let's also check for the specific translation keys used in the file
echo -e "\nChecking specific translation usage in the file..."
rg "t\(['\"].*['\"]\)" web/ce/components/projects/create/attributes.tsx

Length of output: 15288

web/ce/constants/dashboard.ts (1)

16-18: LGTM: Good separation of concerns in type definition

The addition of a separate key property for translations while maintaining value for internal usage is a good practice for i18n implementation.

web/core/components/workspace/sidebar/workspace-menu.tsx (1)

166-166: Verify workspace feature check

The feature check uses the new value property instead of key. Ensure all feature flag configurations have been updated accordingly.

✅ Verification successful

Let me check the type definition and usage of TSidebarWorkspaceMenuItemKeys to understand how the feature keys are structured.


Let me check how the workspace menu items are defined and used to understand if there's any mismatch between key and value properties.


Let me check the actual implementation of the workspace menu items to see how the value property is being used.


Feature check implementation is correctly using the value property

Looking at the implementation in web/ce/constants/dashboard.ts, the workspace menu items are properly defined with both value and key properties, where the value property matches exactly with the TSidebarWorkspaceMenuItemKeys type ("projects", "all-issues", "active-cycles", "analytics"). The isWorkspaceFeatureEnabled function correctly expects and uses these value properties as its featureKey parameter.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for feature flag configurations that might still be using the old 'key' property
rg -g '!*.{lock,min.js,map}' -A 3 'isWorkspaceFeatureEnabled'

Length of output: 1079


Script:

#!/bin/bash
# Search for TSidebarWorkspaceMenuItemKeys type definition and its usage
rg -g '!*.{lock,min.js,map}' 'TSidebarWorkspaceMenuItemKeys'

# Also search for the link.value usage context
ast-grep --pattern 'const $_ = [
  $$$
  {
    $$$
    value: $_,
    $$$
  }
  $$$
]'

Length of output: 1100


Script:

#!/bin/bash
# Search for SIDEBAR_WORKSPACE_MENU definition
rg -g '!*.{lock,min.js,map}' -A 10 'SIDEBAR_WORKSPACE_MENU\s*=' 

# Also search for any other usage of key property in workspace menu
rg -g '!*.{lock,min.js,map}' -B 2 -A 2 'key:.*workspace'

Length of output: 784


Script:

#!/bin/bash
# Search for the workspace menu items implementation
rg -g '!*.{lock,min.js,map}' -A 15 'WORKSPACE_MENU_ITEMS\s*='

# Also check for any migration or changes related to key/value properties
rg -g '!*.{lock,min.js,map}' -B 2 -A 2 'value:\s*["'\''](?:projects|all-issues|active-cycles|analytics)['\''"]\s*,'

Length of output: 1264

packages/i18n/src/config/index.ts (1)

15-20: Verify translation completeness.

Ensure all languages have the same translation keys to prevent runtime errors.

✅ Verification successful

Let me try a different approach to verify the translation files.


Based on the output, I can now provide a final response as I have verified all translation files and their contents.

All languages have complete and matching translation keys.

I have verified that all four language files (en, fr, es, ja) contain the same set of translation keys, and each key has a corresponding translated value in the respective language. The translations are comprehensive and well-maintained across all supported languages, with no missing keys that could cause runtime errors.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for missing translations across language files

# Function to extract keys from a JSON file
extract_keys() {
  jq -r 'paths(scalars) | join(".")' "$1" | sort
}

# Compare translation files with English (base) translations
for lang in fr es ja; do
  echo "Checking $lang translations..."
  diff <(extract_keys "packages/i18n/src/locales/en/translations.json") \
       <(extract_keys "packages/i18n/src/locales/$lang/translations.json")
done

Length of output: 1550


Script:

#!/bin/bash
# First, let's check if these translation files exist and see their content
echo "Checking English translations:"
cat packages/i18n/src/locales/en/translations.json 2>/dev/null || echo "File not found"

echo -e "\nChecking French translations:"
cat packages/i18n/src/locales/fr/translations.json 2>/dev/null || echo "File not found"

echo -e "\nChecking Spanish translations:"
cat packages/i18n/src/locales/es/translations.json 2>/dev/null || echo "File not found"

echo -e "\nChecking Japanese translations:"
cat packages/i18n/src/locales/ja/translations.json 2>/dev/null || echo "File not found"

# Let's also check the directory structure to ensure we're looking in the right place
echo -e "\nChecking directory structure:"
fd -t f . packages/i18n/src

Length of output: 60106

web/app/[workspaceSlug]/(projects)/active-cycles/header.tsx (1)

3-3: LGTM! Verify translation key existence.

The i18n implementation looks good. The component has been properly updated to support translations.

Let's verify the translation key exists in all language files:

Also applies to: 11-31

✅ Verification successful

Translation key verified and properly implemented across all languages

The "active_cycles" translation key is present and correctly defined in all language files (en, es, fr, ja) with appropriate translations for each locale.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the translation key exists in all language files
rg -l "active_cycles" packages/i18n/src/locales/

Length of output: 236


Script:

#!/bin/bash
# Check the actual content of translation files to verify the key exists with proper value
rg "active_cycles" packages/i18n/src/locales/ -A 1 -B 1

Length of output: 1971

packages/i18n/src/components/index.tsx (1)

4-4: Ensure type safety for Language enum.

Verify that the Language type is properly defined as an enum or union type for type safety.

✅ Verification successful

Let me check the definition of languages to ensure complete type safety.


Type safety for Language is properly implemented

The Language type is correctly defined as a union type derived from the languages constant array using as const assertion. This creates a type-safe union of literal string types ("en" | "fr" | "es" | "ja"), ensuring strict type checking for language values throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check Language type definition
rg -A 5 "export (type|enum) Language" packages/i18n/src/

Length of output: 396


Script:

#!/bin/bash
# Check languages definition
rg "export const languages" -A 5 packages/i18n/src/

Length of output: 385

web/app/profile/notifications/page.tsx (1)

5-5: LGTM: Translation hook integration

The useTranslation hook is correctly imported and initialized.

Also applies to: 16-16

web/app/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx (1)

5-5: Verify translation keys for tab labels

The implementation looks good, but we should verify that all tab labels have corresponding translations defined.

Also applies to: 18-18, 36-36

✅ Verification successful

Let me analyze the translation files to verify if all tab labels have corresponding translations.


All tab labels have corresponding translations

I've verified that all tab labels used in the profile constants ("Summary", "Assigned", "Subscribed", "Activity") have corresponding translations in all language files (en, es, fr, ja). The implementation is correct and complete.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all tab labels have corresponding translations

# Extract tab labels from constants
echo "Checking PROFILE_VIEWER_TAB and PROFILE_ADMINS_TAB for translation keys..."
rg -A 5 "PROFILE_.*_TAB.*=.*\[" 

# Search for these keys in translation files
echo "Searching for translation keys in i18n files..."
fd -e json . | xargs cat

Length of output: 97915


Script:

#!/bin/bash
# Extract tab labels from the profile constants
echo "Checking tab labels in profile constants..."
rg -A 2 'key: ".*",' web/core/constants/profile.ts

# Search for these keys in translation files
echo "Searching for corresponding translations..."
rg '"summary"|"assigned"|"created"|"subscribed"' packages/i18n/src/locales/

Length of output: 2139

web/app/provider.tsx (1)

45-55: LGTM! TranslationProvider is correctly positioned

The TranslationProvider is appropriately placed high in the component tree, ensuring translation context is available throughout the application.

web/app/profile/activity/page.tsx (2)

60-67: LGTM! Translation implementation for activity section

The translation keys are appropriately used for the activity title and load more button.


Line range hint 48-48: Verify translation support in EmptyState component

The EmptyState component is used with EmptyStateType.PROFILE_ACTIVITY. Ensure this component supports translations.

web/app/[workspaceSlug]/(projects)/analytics/header.tsx (1)

7-7: LGTM! Verify translation key existence.

The translation integration looks good. The component correctly uses the translation hook for internationalizing the "analytics" text.

Let's verify the translation key exists in all language files:

Also applies to: 17-17, 44-44

✅ Verification successful

Translation key "analytics" is properly configured in all language files

The "analytics" translation key is present and correctly translated in all supported languages:

  • English (en): "Analytics"
  • Spanish (es): "Analítica"
  • French (fr): "Analyse"
  • Japanese (ja): "分析"
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if "analytics" key exists in all language files
fd . --extension json --exec grep -l "\"analytics\"" {} \;

Length of output: 257


Script:

#!/bin/bash
# Check the actual content of translation files to verify the "analytics" key
for locale in en es fr ja; do
  echo "=== $locale translation ==="
  rg "analytics" "packages/i18n/src/locales/$locale/translations.json" -C 2
done

Length of output: 1911

web/core/lib/wrappers/store-wrapper.tsx (1)

5-5: Verify Language enum values.

Ensure the Language enum includes all supported languages (French, Spanish, Japanese).

✅ Verification successful

Language enum includes all required languages

Based on the search results, the Language type is derived from the languages constant in packages/i18n/src/config/index.ts which includes all the required languages:

  • French ("fr")
  • Spanish ("es")
  • Japanese ("ja")
  • English ("en")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check Language enum definition
ast-grep --pattern 'enum Language {
  $$$
}'

Length of output: 46


Script:

#!/bin/bash
# Search for Language type/enum definition using ripgrep
rg -A 10 "type Language = |enum Language |export type Language" 

# Also search for language-related constants or configurations
rg -A 10 "languages|LANGUAGES" -g "!*.lock" -g "!*.log"

Length of output: 66312


Script:

#!/bin/bash
# Search for language-related configurations and constants
rg -A 5 "languages = \[|SUPPORTED_LANGUAGES = \[|const languages" -g "!*.lock" -g "!*.log"

# Also search for language-related imports and type definitions
rg -A 5 "import.*Language|type Language" -g "!*.lock" -g "!*.log"

Length of output: 4124

web/core/components/global/product-updates/footer.tsx (1)

15-41: 🛠️ Refactor suggestion

Maintain consistency in translations.

The text "Discord" is not translated while other link texts are. Consider translating it for consistency.

-       Discord
+       {t("discord")}

Likely invalid or redundant comment.

web/core/components/core/theme/theme-switch.tsx (2)

4-4: LGTM: Translation hook implementation

The useTranslation hook is properly imported and initialized.

Also applies to: 17-17


44-44: Verify translation keys existence

Please ensure that all translation keys (value.key, themeOption.key, and "select_your_theme") exist in the translation files for all supported languages (French, Spanish, Japanese).

Also applies to: 47-47

✅ Verification successful

Let me check the actual content of these translation files to verify if all the required keys exist.


Let me check the theme options and their corresponding translation keys to complete the verification.


Let me check the specific translation keys used in the theme component.


All translation keys are properly defined across all supported languages

Based on the verification results, all the required translation keys (value.key, themeOption.key, and select_your_theme) are properly defined in all supported language files (English, Spanish, French, and Japanese). The theme-related translations include:

  • System preference (system_preference)
  • Theme selection prompt (select_your_theme)
  • Theme options (light, dark, etc.)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if translation keys exist in all language files
# Look for translation files and verify keys

# Search for translation files
echo "Searching for translation files..."
fd -e json -e yaml -e yml . | grep -i "translation\|locale\|lang"

# Search for theme-related translation keys
echo "Checking for theme-related translations..."
rg -l "select_your_theme" 

Length of output: 691


Script:

#!/bin/bash
# Check content of translation files for theme-related keys
echo "English translations:"
jq '.theme' packages/i18n/src/locales/en/translations.json

echo -e "\nFrench translations:"
jq '.theme' packages/i18n/src/locales/fr/translations.json

echo -e "\nSpanish translations:"
jq '.theme' packages/i18n/src/locales/es/translations.json

echo -e "\nJapanese translations:"
jq '.theme' packages/i18n/src/locales/ja/translations.json

# Also let's check the actual usage in the theme-switch component
echo -e "\nTheme switch component usage:"
cat web/core/components/core/theme/theme-switch.tsx

Length of output: 3051


Script:

#!/bin/bash
# Check theme options constants
echo "Theme options constants:"
rg -A 10 "THEME_OPTIONS.*=" .

# Check all theme-related translations
echo -e "\nAll theme-related translations in all languages:"
for lang in en es fr ja; do
    echo -e "\n$lang translations:"
    jq '.theme, .settings.theme' "packages/i18n/src/locales/$lang/translations.json"
done

Length of output: 4845


Script:

#!/bin/bash
# Check for specific theme-related keys in translation files
echo "Checking for system_preference key:"
rg -l "system_preference" packages/i18n/src/locales/

echo -e "\nChecking for select_your_theme key:"
rg -l "select_your_theme" packages/i18n/src/locales/

# Get the actual content around these keys
echo -e "\nContent around theme-related keys in English translations:"
rg -A 2 -B 2 "system_preference|select_your_theme" packages/i18n/src/locales/en/translations.json

echo -e "\nContent around theme-related keys in Spanish translations:"
rg -A 2 -B 2 "system_preference|select_your_theme" packages/i18n/src/locales/es/translations.json

echo -e "\nContent around theme-related keys in French translations:"
rg -A 2 -B 2 "system_preference|select_your_theme" packages/i18n/src/locales/fr/translations.json

echo -e "\nContent around theme-related keys in Japanese translations:"
rg -A 2 -B 2 "system_preference|select_your_theme" packages/i18n/src/locales/ja/translations.json

Length of output: 3240

web/core/constants/cycle.ts (1)

Line range hint 96-135: Verify translation coverage

Ensure that all new cycle-related translation keys are present in all language files (French, Spanish, Japanese).

✅ Verification successful

Let me verify the exact content of these translation files to ensure all the new cycle-related keys are properly included.


All cycle-related translations are properly covered in all language files

The verification shows that all six new cycle-related keys and their descriptions are present in all four language files (English, Spanish, French, and Japanese) with appropriate translations. Each key has both a title and a description variant properly translated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify translation coverage for cycle-related content

# Search for translation files
echo "Searching for cycle-related translations..."
rg -l "cycle_view_title|cycle_view_description" 

# Count occurrences in each language file
echo "Checking translation coverage..."
fd -e json -e yaml -e yml . | grep -i "translation\|locale\|lang" | \
  xargs rg -c "10000_feet_view|get_snapshot_of_each_active_cycle|compare_burndowns|quickly_see_make_or_break_issues|zoom_into_cycles_that_need_attention|stay_ahead_of_blockers"

Length of output: 666


Script:

#!/bin/bash
# Check the actual content of translation files for these specific keys
for key in "10000_feet_view" "get_snapshot_of_each_active_cycle" "compare_burndowns" "quickly_see_make_or_break_issues" "zoom_into_cycles_that_need_attention" "stay_ahead_of_blockers"; do
  echo "=== Checking key: $key ==="
  rg -A 1 "\"$key\"" packages/i18n/src/locales/
done

Length of output: 9569

web/core/components/account/password-strength-meter.tsx (1)

4-4: LGTM: Translation hook integration

The useTranslation hook is properly imported and initialized.

Also applies to: 21-21

web/core/components/workspace/sidebar/user-menu.tsx (1)

67-68: 🛠️ Refactor suggestion

Inconsistent usage of link.key vs link.value

The conditions are using link.value while translations use link.key. This mixing of identifiers could lead to maintenance issues. Consider using consistent identifiers for better maintainability.

- if (link.value === "drafts" && draftIssueCount === 0) return null;
- if (!isUserFeatureEnabled(link.value)) return null;
+ if (link.key === "drafts" && draftIssueCount === 0) return null;
+ if (!isUserFeatureEnabled(link.key)) return null;

Likely invalid or redundant comment.

web/app/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx (1)

7-7: Verify translation key usage across the application

Let's ensure consistent usage of these translation keys across the application.

Also applies to: 36-36

✅ Verification successful

Based on the search results, I can see that:

  1. The translation key "you_do_not_have_the_permission_to_access_this_page" is properly defined in all language files (en, es, fr, ja) in packages/i18n/src/locales/
  2. The key is used correctly in web/app/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx with the useTranslation hook
  3. The translation system appears to be set up and working properly across the application

Translation key is properly implemented and localized

The translation key is correctly defined in all language files and used appropriately in the codebase. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for hardcoded error messages that should be translated
rg -l "permission|access|denied" --type ts --type tsx

# Search for translation key usage
rg "you_do_not_have_the_permission_to_access_this_page" --type ts --type tsx

Length of output: 188


Script:

#!/bin/bash
# Search for hardcoded error messages that should be translated (without file type flags)
rg -l "permission|access|denied"

# Search for translation key usage
rg "you_do_not_have_the_permission_to_access_this_page"

# Look for other translation key usages in the codebase
rg "useTranslation|t\(['\"]"

Length of output: 84589

web/core/components/workspace/sidebar/quick-actions.tsx (1)

5-5: LGTM! Translation implementation looks good

The translation hook is properly imported and used to translate the "New issue" text.

Also applies to: 19-19, 97-97

web/core/components/project/settings/features-list.tsx (2)

5-5: LGTM! Consistent translation implementation

The translation implementation is consistent across all text elements, following a clear pattern for features and their descriptions.

Also applies to: 24-24, 67-68, 84-84, 92-92


67-68: Verify translation key existence

The implementation consistently uses translation keys, but we should verify that all required keys exist in the translation files:

  • Feature section keys: {feature.key} and ${feature.key}_description
  • Feature item keys: {featureItem.key} and ${featureItem.key}_description

Also applies to: 84-84, 92-92

web/ce/components/projects/create/root.tsx (1)

6-6: LGTM! Basic translation implementation

The translation hook is properly integrated for static text elements like success and error titles.

Also applies to: 51-51, 69-70, 100-101, 112-112

web/core/components/project/create/common-attributes.tsx (1)

5-5: Well-implemented internationalization!

The translation integration is comprehensive and consistent:

  • All user-facing strings are properly translated
  • Validation messages use translation keys
  • Form placeholders are internationalized

Also applies to: 30-30, 55-130

packages/types/src/users.d.ts (1)

Line range hint 1-64: Verify the impact of removing the role field

The removal of the role field from IUser interface might affect existing code that relies on this field.

web/app/create-workspace/page.tsx (1)

8-8: Well-structured internationalization implementation!

The translation integration is thorough and consistent:

  • All static text is properly translated
  • Image alt texts are internationalized
  • UI components use translation keys consistently

Also applies to: 26-26, 70-103

web/core/components/workspace/sidebar/project-navigation.tsx (2)

21-21: LGTM: Type definition enhancement for i18n support

The addition of the key property to TNavigationItem type properly supports internationalization while maintaining type safety.


Line range hint 60-112: Verify translation keys in locale files

The navigation items now use translation keys instead of hardcoded strings. While the implementation is correct, we should ensure all keys are defined in the locale files.

✅ Verification successful

Let me verify the actual content of these translation keys to ensure they are properly defined and not just partial matches.


Let me fix the regex syntax and try again.


All navigation item translation keys are properly defined

All the required translation keys ("issues", "cycles", "modules", "views", "pages", "intake") are present in the English locale file with their corresponding translations. The keys are also available in other locale files (French, Spanish, and Japanese) as verified in the first check.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all navigation item keys exist in locale files
# Expected results: All keys should be found in the locale files

# Find all locale files
echo "Searching for translation keys in locale files..."
for key in "issues" "cycles" "modules" "views" "pages" "intake"; do
  echo "Checking key: $key"
  rg -l "\"$key\":" --type json
done

Length of output: 2127


Script:

#!/bin/bash
# Check the actual content of these keys in the English locale file
echo "Checking English translations content:"
rg -A 1 '"(issues|cycles|modules|views|pages|intake)":\s*{?' packages/i18n/src/locales/en/translations.json

Length of output: 378


Script:

#!/bin/bash
# Check the actual content of these keys in the English locale file
echo "Checking English translations content:"
for key in "issues" "cycles" "modules" "views" "pages" "intake"; do
  echo "=== Content for key: $key ==="
  rg -A 2 "\"${key}\":" packages/i18n/src/locales/en/translations.json
done

Length of output: 1781

web/core/components/profile/notification/email-notification-form.tsx (1)

63-64: Verify form translation keys

The form labels and descriptions have been properly internationalized. Let's verify that all translation keys exist in the locale files.

Also applies to: 85-87, 109-110, 131-133, 155-157

✅ Verification successful

Translation keys verified successfully

All form-related translation keys are present in all supported locale files (en, es, fr, ja). Each key exists in the translation files at packages/i18n/src/locales/*/translations.json.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all form-related translation keys exist
# Expected results: All keys should be found in the locale files

echo "Searching for form translation keys..."
keys=(
  "property_changes"
  "property_changes_description"
  "state_change"
  "state_change_description"
  "issue_completed"
  "issue_completed_description"
  "comments"
  "comments_description"
  "mentions"
  "mentions_description"
)

for key in "${keys[@]}"; do
  echo "Checking key: $key"
  rg -l "\"$key\":" --type json
done

Length of output: 3627

web/core/store/user/profile.store.ts (1)

61-61: Add language validation in updateUserProfile

Consider adding validation for the language value when updating the user profile to ensure only supported languages are set.

web/app/profile/security/page.tsx (1)

7-7: LGTM: Translation setup is properly implemented

The translation hook is correctly imported and initialized at the component level.

Also applies to: 59-60

web/core/components/core/theme/custom-theme-selector.tsx (1)

74-82: LGTM: Toast messages are properly internationalized

The success and error messages in the toast notifications are correctly implemented with translations.

web/app/invitations/page.tsx (1)

156-157: LGTM: User-facing messages are properly internationalized

All user-facing messages, including empty states and action buttons, are correctly implemented with translations.

Also applies to: 226-227, 230-230

packages/i18n/src/locales/ja/translations.json (1)

213-223: ⚠️ Potential issue

Untranslated content detected

Several strings from line 213 to 223 are still in English and need to be translated to Japanese.

Apply these translations:

-  "removing_project_from_favorites": "Removing project from favorites",
-  "project_removed_from_favorites": "Project removed from favorites",
+  "removing_project_from_favorites": "お気に入りからプロジェクトを削除中",
+  "project_removed_from_favorites": "プロジェクトがお気に入りから削除されました",

Likely invalid or redundant comment.

web/core/components/project/form.tsx (1)

6-6: LGTM: Translation hook implementation

The useTranslation hook is correctly imported and initialized. The implementation follows i18n best practices.

Also applies to: 47-47

web/core/components/workspace/sidebar/projects-list-item.tsx (2)

17-17: LGTM: Translation hook integration

The translation hook is properly imported and initialized at the component level, following React hooks best practices.

Also applies to: 53-53


350-350: LGTM: Comprehensive menu item translations

All menu items are properly internationalized, maintaining consistency throughout the component.

Also applies to: 362-362, 379-379, 387-387, 396-396, 405-405

web/app/profile/page.tsx (2)

4-4: Successful integration of translation capabilities

The use of useTranslation and the appropriate application of translation keys with t() enhance the application's language support. The implementation aligns well with the PR objectives and follows best practices for internationalization.

Also applies to: 13-13, 26-26


28-28: Correct integration of ProfileForm component

The ProfileForm component is correctly integrated into the ProfileSettingsPage, and the required props user and profile are passed appropriately. This modular approach improves code readability and maintainability.

web/ce/constants/dashboard.ts Show resolved Hide resolved
packages/i18n/src/hooks/use-translation.ts Show resolved Hide resolved
packages/i18n/src/config/index.ts Show resolved Hide resolved
web/core/store/user/profile.store.ts Show resolved Hide resolved
packages/i18n/src/locales/es/translations.json Outdated Show resolved Hide resolved
web/core/components/project/form.tsx Show resolved Hide resolved
web/core/components/profile/form.tsx Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
web/core/components/account/deactivate-account-modal.tsx (1)

Line range hint 37-44: Add translations for toast notifications.

The success and error messages in the toast notifications are still hardcoded in English. Consider internationalizing these messages for consistency:

 setToast({
   type: TOAST_TYPE.SUCCESS,
-  title: "Success!",
-  message: "Account deactivated successfully.",
+  title: t("success"),
+  message: t("account_deactivated_successfully"),
 });
🧹 Nitpick comments (1)
web/core/components/account/deactivate-account-modal.tsx (1)

Line range hint 33-44: Consider separating business logic from UI component.

The account deactivation logic could be moved to a custom hook (e.g., useAccountDeactivation) to:

  • Improve separation of concerns
  • Make the component more focused on UI rendering
  • Facilitate better testing of business logic
  • Enable reuse of deactivation logic if needed elsewhere

Example structure:

// hooks/useAccountDeactivation.ts
export const useAccountDeactivation = () => {
  const { t } = useTranslation();
  const { deactivateAccount, signOut } = useUser();
  const router = useAppRouter();

  const handleDeactivation = async () => {
    try {
      await deactivateAccount();
      setToast({
        type: TOAST_TYPE.SUCCESS,
        title: t("success"),
        message: t("account_deactivated_successfully"),
      });
      signOut();
      router.push("/");
      return true;
    } catch (err: any) {
      setToast({
        type: TOAST_TYPE.ERROR,
        title: t("error"),
        message: err?.error,
      });
      return false;
    }
  };

  return { handleDeactivation };
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07c5147 and e1fede3.

📒 Files selected for processing (5)
  • packages/i18n/src/locales/en/translations.json (1 hunks)
  • packages/i18n/src/locales/es/translations.json (1 hunks)
  • packages/i18n/src/locales/fr/translations.json (1 hunks)
  • packages/i18n/src/locales/ja/translations.json (1 hunks)
  • web/core/components/account/deactivate-account-modal.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/i18n/src/locales/en/translations.json
  • packages/i18n/src/locales/es/translations.json
  • packages/i18n/src/locales/fr/translations.json
  • packages/i18n/src/locales/ja/translations.json
🔇 Additional comments (1)
web/core/components/account/deactivate-account-modal.tsx (1)

6-6: LGTM! Translation hook integration is correct.

The useTranslation hook is properly imported and initialized.

Also applies to: 22-22

mathalav55 and others added 8 commits December 18, 2024 12:45
* chore: package code refactoring

* chore: component restructuring and refactor

* chore: comment create improvement
…own (#6211)

* enhancement:added functionality to add features directly from dropdown

* fix: fixed import order

* fix: fixed lint errors
* chore: added common component for project activity

* fix: added enum

* fix: added enum for initiatives
- Handle edge cases in sync workspace
@mathalav55 mathalav55 marked this pull request as draft December 18, 2024 07:19
@mathalav55 mathalav55 marked this pull request as ready for review December 18, 2024 07:32
@mathalav55 mathalav55 marked this pull request as draft December 18, 2024 08:27
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🔭 Outside diff range comments (3)
web/core/components/dropdowns/priority.tsx (1)

Line range hint 314-314: Replace hardcoded placeholder default value

The default value for the placeholder prop is still hardcoded in English. Consider using the translation function here as well.

-  placeholder = "Priority",
+  placeholder = t("priority"),
web/core/components/dropdowns/project.tsx (1)

Internationalization improvements needed

The following hardcoded strings need to be wrapped with the translation hook:

  • Default placeholder "Project"
  • Tooltip heading "Project"
  • Dynamic string construction for project count (${value.length} project${value.length !== 1 ? "s" : ""})

Currently only these strings are translated:

  • "search"
  • "no_matching_results"
  • "loading"
🔗 Analysis chain

Line range hint 1-277: Verify complete internationalization coverage

Some potentially untranslated strings were found in the component:

  • "Project" in tooltipHeading
  • "project"/"projects" in tooltipContent

Let's verify if any other user-facing strings in the component or related files need translation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for hardcoded strings that might need translation
rg -i --type tsx --type ts 'tooltip(Heading|Content).*["'\''].*["'\'']' web/core/components/dropdowns/

Length of output: 132


Script:

#!/bin/bash
# Search for hardcoded strings that might need translation in the dropdown components
rg -t js -t jsx -t ts -t tsx 'tooltip(Heading|Content).*["'\''].*["'\'']' web/core/components/dropdowns/

# Search for other potential hardcoded strings in the component
rg -t js -t jsx -t ts -t tsx '"[^"]+"|\'[^\']+\'' web/core/components/dropdowns/project.tsx

Length of output: 251


Script:

#!/bin/bash
# Search for hardcoded strings in the project dropdown component
rg -g '*.{ts,tsx}' '"[^"]*"' web/core/components/dropdowns/project.tsx

# Check usage of translation hook in the component
rg -g '*.{ts,tsx}' 't\([^)]+\)' web/core/components/dropdowns/project.tsx

Length of output: 3810

web/core/components/issues/issue-modal/base.tsx (1)

Missing translation key "issue" in all locales

The translation key "issue" is missing in all locale files (returns null), while it's being used in the error message construction: ${is_draft_issue ? t("draft_issue") : t("issue")} ${t("could_not_be_created")}. This could lead to incomplete error messages being displayed to users.

  • The key "issue" should be added to all translation files:
    • packages/i18n/src/locales/en/translations.json
    • packages/i18n/src/locales/es/translations.json
    • packages/i18n/src/locales/fr/translations.json
    • packages/i18n/src/locales/ja/translations.json

All other translation keys are properly defined across all supported locales.

🔗 Analysis chain

Line range hint 220-303: Verify translation key coverage

Let's ensure all translation keys used in the component are properly defined in the translation files.


Let me try a different approach to locate and verify the translation files.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all used translation keys exist in the translation files

# Find all translation keys used in this file
echo "Translation keys used in the file:"
rg -o 't\("([^"]+)"\)' web/core/components/issues/issue-modal/base.tsx | cut -d'"' -f2

# Check if these keys exist in the translation files
echo -e "\nChecking translation files for these keys:"
for locale in en es fr ja; do
  echo "Checking $locale locale..."
  if [ -f "packages/i18n/src/locales/$locale.json" ]; then
    jq 'keys' "packages/i18n/src/locales/$locale.json"
  fi
done

Length of output: 959


Script:

#!/bin/bash
# Let's first find where the translation files might be located
fd -t f -e json . | grep -i 'locale\|translation\|lang'

# Then let's check the content of package.json files to find i18n related configurations
fd package.json -t f -x jq -r 'select(.dependencies != null) | .dependencies | keys[] | select(contains("i18n") or contains("translate") or contains("intl"))'

Length of output: 418


Script:

#!/bin/bash
# Now that we found the translation files, let's check for the required keys
echo "Translation keys used in the file:"
keys=(
  "success"
  "draft_created"
  "issue_created_successfully"
  "error"
  "draft_issue"
  "issue"
  "could_not_be_created"
  "please_try_again"
  "issue_updated_successfully"
  "issue_could_not_be_updated"
)

for key in "${keys[@]}"; do
  echo -e "\nChecking key: $key"
  for locale in en es fr ja; do
    echo "[$locale]"
    jq ".[\"$key\"]" "packages/i18n/src/locales/$locale/translations.json" 2>/dev/null || echo "Key not found"
  done
done

Length of output: 6908

🧹 Nitpick comments (11)
web/core/components/issues/issue-modal/form.tsx (1)

95-98: Consider extracting translation logic for better readability

While the implementation is functionally correct, the nested ternary operations with template literals make the code harder to read.

Consider extracting the logic into helper functions:

-    modalTitle = `${data?.id ? t("update") : isDraft ? t("create_a_draft") : t("create_new_issue")}`,
-    primaryButtonText = {
-      default: `${data?.id ? t("update") : isDraft ? t("save_to_drafts") : t("save")}`,
-      loading: `${data?.id ? t("updating") : t("saving")}`,
+    modalTitle = getModalTitle(data?.id, isDraft, t),
+    primaryButtonText = {
+      default: getDefaultButtonText(data?.id, isDraft, t),
+      loading: getLoadingButtonText(data?.id, t),
     },

Add these helper functions:

const getModalTitle = (hasId: boolean, isDraft: boolean, t: TranslationFunction) => 
  hasId ? t("update") : isDraft ? t("create_a_draft") : t("create_new_issue");

const getDefaultButtonText = (hasId: boolean, isDraft: boolean, t: TranslationFunction) =>
  hasId ? t("update") : isDraft ? t("save_to_drafts") : t("save");

const getLoadingButtonText = (hasId: boolean, t: TranslationFunction) =>
  hasId ? t("updating") : t("saving");
web/core/components/issues/issue-modal/components/title-input.tsx (2)

34-37: Consider extracting repeated translation keys

The translation key "title_is_required" is used multiple times in the code. Consider extracting it to a constant to improve maintainability and reduce the risk of typos.

+ const TRANSLATION_KEYS = {
+   TITLE_REQUIRED: "title_is_required",
+   TITLE_MAX_LENGTH: "title_should_be_less_than_255_characters",
+   TITLE_PLACEHOLDER: "title"
+ } as const;

  const validateWhitespace = (value: string) => {
    if (value.trim() === "") {
-     return t("title_is_required");
+     return t(TRANSLATION_KEYS.TITLE_REQUIRED);
    }
    return undefined;
  };

Line range hint 1-74: Consider implementing i18n type safety

To improve the robustness of the internationalization implementation, consider:

  1. Using TypeScript template literal types for translation keys to catch typos at compile time
  2. Implementing a translation key validation system during the build process
  3. Adding runtime fallback messages for missing translations

This would help prevent issues with missing or incorrect translations in production.

packages/i18n/src/locales/es/translations.json (1)

1-317: Consider adding missing common UI translations

The translation file might be missing some common UI elements:

  • Error states (404, 500, etc.)
  • Common actions (edit, delete, etc.)
  • Form validation messages

Also, consider organizing keys into logical groups using nested objects for better maintainability:

{
+  "common": {
+    "actions": {
+      "edit": "Editar",
+      "delete": "Eliminar",
+      // ...
+    },
+    "errors": {
+      "not_found": "Página no encontrada",
+      "server_error": "Error del servidor",
+      // ...
+    }
+  },
   // ... rest of the translations
}
web/core/components/dropdowns/project.tsx (3)

238-238: Consider using a more specific translation key

The current translation key "search" is quite generic. Consider using a more context-specific key like "project_search_placeholder" to avoid potential conflicts and improve maintainability.

-placeholder={t("search")}
+placeholder={t("project_search_placeholder")}

268-268: Consider using a more specific translation key

The translation key "no_matching_results" could be more specific to the project context.

-<p className="text-custom-text-400 italic py-1 px-1.5">{t("no_matching_results")}</p>
+<p className="text-custom-text-400 italic py-1 px-1.5">{t("project_search_no_results")}</p>

271-271: Consider enhancing loading state and translation key

The current implementation has two suggestions for improvement:

  1. The translation key "loading" is too generic
  2. The loading state could benefit from a more informative message
-<p className="text-custom-text-400 italic py-1 px-1.5">{t("loading")}</p>
+<p className="text-custom-text-400 italic py-1 px-1.5">{t("project_list_loading")}</p>

Consider adding a loading skeleton or spinner for a better user experience during the loading state.

web/core/components/dropdowns/state.tsx (2)

165-166: Consider using centralized translation keys

While the translation implementation is functional, consider using centralized translation key constants instead of string literals. This would make it easier to maintain and refactor translations across the application.

Example implementation:

// constants/translations.ts
export const TRANSLATION_KEYS = {
  STATE: {
    LABEL: 'state',
    TOOLTIP: {
      HEADING: 'state',
      CONTENT: 'state'
    }
  }
} as const;

// Then in the component:
t(TRANSLATION_KEYS.STATE.LABEL)

Also applies to: 183-183


244-244: Consider extracting common UI messages

These are common UI messages that might be reused across different components. Consider extracting them into shared translation constants.

Example implementation:

// constants/common-messages.ts
export const COMMON_MESSAGES = {
  NO_RESULTS: 'no_matching_results',
  LOADING: 'loading'
} as const;

// Then in components:
t(COMMON_MESSAGES.NO_RESULTS)
t(COMMON_MESSAGES.LOADING)

Also applies to: 247-247

web/core/components/dropdowns/member/member-options.tsx (2)

90-90: Consider cultural naming conventions

The translation of "you" might need to consider formal/informal variants in languages like Japanese (あなた vs 君) and Spanish (tú vs usted).

Consider implementing a user preference for formal/informal language style in the settings.


147-147: Add loading state enhancement

The loading and no results states could benefit from more contextual information.

Consider enhancing the user experience:

-<p className="px-1.5 py-1 italic text-custom-text-400">{t("loading")}</p>
+<div className="px-1.5 py-1 flex items-center gap-2">
+  <span className="animate-spin">⏳</span>
+  <p className="italic text-custom-text-400">{t("loading_members")}</p>
+</div>

Also applies to: 150-150

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed5ff98 and fdcc233.

📒 Files selected for processing (16)
  • packages/i18n/src/locales/en/translations.json (1 hunks)
  • packages/i18n/src/locales/es/translations.json (1 hunks)
  • packages/i18n/src/locales/fr/translations.json (1 hunks)
  • packages/i18n/src/locales/ja/translations.json (1 hunks)
  • web/ce/types/projects/index.ts (1 hunks)
  • web/ce/types/projects/project-activity.ts (1 hunks)
  • web/core/components/dropdowns/member/index.tsx (5 hunks)
  • web/core/components/dropdowns/member/member-options.tsx (5 hunks)
  • web/core/components/dropdowns/priority.tsx (11 hunks)
  • web/core/components/dropdowns/project.tsx (4 hunks)
  • web/core/components/dropdowns/state.tsx (5 hunks)
  • web/core/components/issues/issue-modal/base.tsx (6 hunks)
  • web/core/components/issues/issue-modal/components/default-properties.tsx (11 hunks)
  • web/core/components/issues/issue-modal/components/title-input.tsx (4 hunks)
  • web/core/components/issues/issue-modal/form.tsx (7 hunks)
  • web/core/components/issues/select/label.tsx (6 hunks)
✅ Files skipped from review due to trivial changes (1)
  • web/ce/types/projects/project-activity.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/i18n/src/locales/ja/translations.json
  • packages/i18n/src/locales/fr/translations.json
  • packages/i18n/src/locales/en/translations.json
🔇 Additional comments (28)
web/core/components/issues/issue-modal/form.tsx (3)

9-10: LGTM: Clean import organization

The import for the translation hook is properly organized under a dedicated i18n section.


204-205: LGTM: Proper error message translation

Error messages are correctly internationalized using consistent translation keys.


501-501: LGTM: Consistent translation of UI elements

UI text elements are properly internationalized using consistent translation keys.

Also applies to: 521-521

web/core/components/dropdowns/priority.tsx (5)

8-8: LGTM: Translation hook import

The import of useTranslation hook is correctly placed and follows the project's module structure.


158-163: LGTM: Consistent translation implementation

The translation implementation in BackgroundButton follows the same pattern as BorderButton, maintaining consistency across components.

Also applies to: 207-207


242-247: LGTM: Consistent translation pattern

The TransparentButton component maintains the same translation pattern as other button variants, ensuring a uniform approach to internationalization.

Also applies to: 292-292


343-344: LGTM: Comprehensive translation implementation

The dropdown component has been properly internationalized with all user-facing strings using the translation function, including:

  • Priority option labels
  • Search placeholder
  • No results message

Also applies to: 355-355, 465-465, 491-491


75-80: Verify translation key consistency

The translation keys should align with the defined keys in the translation files. Ensure that:

  • priority key exists for tooltipHeading
  • Priority level keys (urgent, high, medium, low, none) exist

Also applies to: 124-124

✅ Verification successful

Let me verify the exact content of these translation keys to ensure they match our requirements.


Translation keys verified and found consistent

All required translation keys (priority, urgent, high, medium, low, none) are properly defined in the translation files across all supported languages (en, es, fr, ja), and the English translations confirm their correct usage for priority levels.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if all required translation keys exist in translation files
rg -l "\"priority\":|\"urgent\":|\"high\":|\"medium\":|\"low\":|\"none\":" packages/i18n/src/locales/

Length of output: 279


Script:

#!/bin/bash
# Check the actual content of the translation keys in the English locale file
rg -A 1 '"priority":|"urgent":|"high":|"medium":|"low":|"none":' packages/i18n/src/locales/en/translations.json

Length of output: 259

web/core/components/issues/issue-modal/components/title-input.tsx (4)

7-7: LGTM: Clean import addition

The useTranslation hook import is properly placed and follows the established import pattern.


29-29: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized and follows React hooks best practices.


64-64: LGTM: Consistent placeholder translation

The placeholder translation is properly implemented and maintains consistency with other internationalization changes.


46-50: Verify translation keys existence

The translation keys used in the validation rules should exist in the translation files to prevent missing translations at runtime.

✅ Verification successful

Let me verify the actual content of these translation files to ensure the specific keys exist.


Translation keys are properly defined

Both translation keys title_is_required and title_should_be_less_than_255_characters exist in the English translations file with appropriate messages, and the translation files are present for all supported languages (en, es, fr, ja).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the translation keys exist in the translation files

# Search for the translation keys in the translation files
rg -l "title_is_required|title_should_be_less_than_255_characters|title" --type json

Length of output: 274


Script:

#!/bin/bash
# Check the content of English translations file for these specific keys
rg "title_is_required|title_should_be_less_than_255_characters" packages/i18n/src/locales/en/translations.json

Length of output: 246

packages/i18n/src/locales/es/translations.json (1)

1-317: JSON structure looks good!

The file is well-formatted and follows proper JSON syntax standards.

web/ce/types/projects/index.ts (2)

1-2: LGTM! Export statement follows consistent pattern

The new export statement follows the established pattern and maintains good TypeScript practices for type exports.


2-2: Verify the relationship between project activities and i18n

This change introduces project activity types, but it's not immediately clear how this relates to the PR's primary objective of adding language support. Could you please clarify:

  1. How project activities integrate with the new i18n features?
  2. Whether this change should be in a separate PR focused on project activities?
web/core/components/issues/select/label.tsx (2)

8-8: LGTM: Translation hook setup is correct.

The import and initialization of the useTranslation hook follow React best practices and are properly placed within the component.

Also applies to: 42-42


135-135: Verify translation keys and consider adding translator context.

The translation implementation looks good, but let's ensure all keys are properly defined and provide enough context for translators.

Let's verify the translation keys exist in all language files:

Consider adding translator comments to provide context:

-  {t("labels")}
+  {/* Translators: Label text for the issue labels selector button */}
+  {t("labels")}

-  {t("no_matching_results")}
+  {/* Translators: Shown when no labels match the search query */}
+  {t("no_matching_results")}

Also applies to: 156-156, 236-236, 239-239, 248-248

✅ Verification successful

Translation keys are properly defined and widely used

Based on the verification:

  1. All translation keys ("labels", "search", "no_matching_results", "loading", "create_new_label") are defined in the English translations file.
  2. The keys are consistently used across multiple components, indicating they are part of the established translation system.
  3. The translation implementation follows the project's patterns, as evidenced by similar usage in other components.

The suggestion for adding translator comments remains valid as a good practice, but it's not a critical issue.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all translation keys used in the component exist in the translation files
# Expected location of translation files based on the import path: packages/i18n/src/locales/

# Define the keys we're looking for
KEYS=("labels" "search" "no_matching_results" "loading" "create_new_label")

# Find and check all JSON translation files
fd -e json -p "packages/i18n/src/locales/" -x sh -c '
  echo "Checking file: {}"
  for key in "${KEYS[@]}"; do
    if ! jq "has(\"$key\")" {} | grep -q true; then
      echo "⚠️ Missing key: $key in {}"
    fi
  done
'

Length of output: 648


Script:

#!/bin/bash
# Let's try a different approach to check translation keys
# First, let's examine the content of one translation file to understand its structure

echo "=== English translations ==="
cat ./packages/i18n/src/locales/en/translations.json

echo -e "\n=== Searching for translation key usage ==="
# Search for these specific translation keys in the codebase
rg -l "t\([\"']labels[\"']\)" 
rg -l "t\([\"']search[\"']\)"
rg -l "t\([\"']no_matching_results[\"']\)"
rg -l "t\([\"']loading[\"']\)"
rg -l "t\([\"']create_new_label[\"']\)"

Length of output: 18271

web/core/components/dropdowns/project.tsx (2)

7-7: LGTM: Clean import of translation hook

The import is properly organized with other dependencies.


90-90: LGTM: Proper translation hook initialization

The translation hook is correctly initialized at the component level.

web/core/components/dropdowns/state.tsx (3)

9-9: LGTM: Import statement is correctly placed

The import of useTranslation from @plane/i18n is appropriately placed with other imports and is necessary for the internationalization changes.


86-86: LGTM: Translation hook is properly initialized

The useTranslation hook is correctly initialized and destructured to obtain the t function, following React hooks best practices.


9-9: Verify consistent translation key usage across the codebase

Let's verify that these translation keys are used consistently across other components.

Also applies to: 86-86, 165-166, 183-183, 244-244, 247-247

✅ Verification successful

Based on the results from our verification scripts, I can now provide a final response:

Translation implementation is consistent and properly configured

The translation key "state" is:

  • Properly defined in all language files (en, es, fr, ja)
  • Used consistently in the state dropdown component
  • Follows the same pattern as other translation keys ("loading", "no_matching_results")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of translation keys across the codebase

# Search for direct string usage of translation keys
echo "Checking for translation key usage patterns..."
rg -g '*.{ts,tsx}' "t\(['\"]state['\"]\)" --type-add 'tsx:*.tsx'
rg -g '*.{ts,tsx}' "t\(['\"]no_matching_results['\"]\)" --type-add 'tsx:*.tsx'
rg -g '*.{ts,tsx}' "t\(['\"]loading['\"]\)" --type-add 'tsx:*.tsx'

# Look for potential translation key definitions
echo "Checking for translation key definitions..."
rg -g '*.{json,ts,tsx}' -C 2 '"state":\s*{' --type-add 'tsx:*.tsx'

Length of output: 3172


Script:

#!/bin/bash
# Let's check the translation files and state-related components more thoroughly

# Check translation files for state-related keys
echo "Checking translation files..."
fd -e json . | xargs rg '"state":'

# Check for useTranslation hook usage with state
echo "Checking useTranslation with state..."
ast-grep --pattern 'const { t } = useTranslation();
  $$$
  t("state")'

# Check for state dropdown component imports
echo "Checking state dropdown imports..."
rg -g '*.{ts,tsx}' "from.*dropdowns/state"

# Check for other state-related translations
echo "Checking other state translations..."
rg -g '*.{ts,tsx}' 't\(["\'].+state["\']' --type-add 'tsx:*.tsx'

Length of output: 857

web/core/components/issues/issue-modal/components/default-properties.tsx (3)

7-7: LGTM: Translation hook import added correctly

The addition of the useTranslation hook import aligns with the internationalization objectives.


69-69: LGTM: Translation hook initialized properly

The useTranslation hook is correctly initialized at the component level and well-placed with other hooks.


138-138: Verify translation keys existence

All hardcoded strings have been replaced with translation keys. Let's verify that all these keys exist in the translation files to prevent any missing translations at runtime.

Consider adding JSDoc comments to document the translation keys being used in this component, which would help other developers understand and maintain the translations.

/** Translation keys used in this component:
 * @i18n assignees - Placeholder for assignee dropdown
 * @i18n start_date - Placeholder for start date dropdown
 * @i18n due_date - Placeholder for due date dropdown
 * @i18n cycle - Placeholder for cycle dropdown
 * @i18n modules - Placeholder for modules dropdown
 * @i18n estimate - Placeholder for estimate dropdown
 * @i18n change_parent_issue - Text for changing parent issue
 * @i18n remove_parent_issue - Text for removing parent issue
 * @i18n add_parent - Text for adding parent issue
 */

Also applies to: 177-177, 196-196, 214-214, 236-236, 261-261, 293-293, 306-306, 319-319

✅ Verification successful

Let me generate one more verification script to check the content of the translation files directly, as the previous script only checked for exact matches which might have missed the keys if they were nested:

This will help us see the actual structure and content of the translation files to verify if these keys exist, possibly under a different hierarchy or format.


Translation keys exist and are properly defined

After checking the translation files, I can confirm that all the translation keys used in the component are present in the translation files. The keys were found in the English, Spanish, Japanese, and French translation files:

  • "assignees"
  • "start_date"
  • "due_date"
  • "cycle"
  • "modules"
  • "estimate"
  • "change_parent_issue"
  • "remove_parent_issue"
  • "add_parent"

All keys are properly defined with their corresponding translations in each language file.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all translation keys used in the component exist in translation files

# Define the keys to check
KEYS=("assignees" "start_date" "due_date" "cycle" "modules" "estimate" "change_parent_issue" "remove_parent_issue" "add_parent")

# Find and check translation files
echo "Checking translation files for required keys..."
for key in "${KEYS[@]}"; do
  echo "Checking key: $key"
  fd -e json -e yaml -e yml . | while read -r file; do
    if [[ "$file" =~ translations|i18n|locale ]]; then
      if ! grep -q "\"$key\"\\|'$key'" "$file"; then
        echo "Warning: Key '$key' not found in $file"
      fi
    fi
  done
done

Length of output: 42949


Script:

#!/bin/bash
# Check the actual content of translation files
echo "Checking translation files content:"
fd -t f . packages/i18n/src/locales/ -e json -x cat {}

Length of output: 67031

web/core/components/issues/issue-modal/base.tsx (1)

6-6: LGTM: Translation hook integration

The integration of the useTranslation hook follows React best practices and is correctly placed at the component's top level.

Also applies to: 58-58

web/core/components/dropdowns/member/index.tsx (2)

4-4: LGTM: Translation hook integration

The useTranslation hook is correctly imported and initialized.

Also applies to: 30-30


45-45: Verify translation key consistency

The component uses several translation keys: "members", "assignee". Ensure these keys are consistently defined across all language files.

Also applies to: 91-91, 136-136

✅ Verification successful

Let me generate another script to specifically check the translation files, since the previous script included many configuration files that aren't relevant for translations.


Translation keys are properly defined across all language files

The translation keys "members" and "assignee" are consistently defined in all language files (en, es, fr, ja) with appropriate translations for each locale:

  • English (en): "Members", "Assignee"
  • Spanish (es): "Miembros", "Asignado"
  • French (fr): "Membres", "Assigné"
  • Japanese (ja): "メンバー", "アサイン者"
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistency of translation keys across language files

# Find all translation files
fd -e json -e yaml -e yml . | while read -r file; do
  echo "Checking $file for required keys..."
  # Check for the required translation keys
  for key in "members" "assignee"; do
    rg -q "\"$key\":|'$key':" "$file" || echo "Missing key '$key' in $file"
  done
done

Length of output: 26932


Script:

#!/bin/bash
# Search specifically in translation files for the keys
echo "Checking translation files for 'members' and 'assignee' keys..."
rg -l "\"members\":|'members':" "packages/i18n/src/locales/**/translations.json"
echo -e "\nChecking actual content of translation files:"
for lang in packages/i18n/src/locales/*/translations.json; do
  echo -e "\n=== $lang ==="
  rg -A 1 "\"members\":|\"assignee\":" "$lang" || echo "No matches found"
done

Length of output: 1798

Comment on lines 46 to 47
"workspaces": "Workspaces",
"create_workspace": "Crear workspace",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent translation of "workspace" terms

The translation of "workspace" is inconsistent throughout the file:

  • Lines 46-47: Left untranslated as "workspace"
  • Line 270: Translated as "nombre-del-espacio-de-trabajo"

Consider using "espacio de trabajo" consistently throughout the file:

-  "workspaces": "Workspaces",
-  "create_workspace": "Crear workspace",
+  "workspaces": "Espacios de trabajo",
+  "create_workspace": "Crear espacio de trabajo",

Also applies to: 270-270

web/core/components/issues/issue-modal/base.tsx Outdated Show resolved Hide resolved
web/core/components/dropdowns/member/index.tsx Outdated Show resolved Hide resolved
* fix: modified translation for plurals
@mathalav55 mathalav55 marked this pull request as ready for review December 18, 2024 08:45
@mathalav55 mathalav55 marked this pull request as draft December 18, 2024 08:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fdcc233 and fd5b829.

📒 Files selected for processing (6)
  • packages/i18n/src/locales/en/translations.json (1 hunks)
  • packages/i18n/src/locales/es/translations.json (1 hunks)
  • packages/i18n/src/locales/fr/translations.json (1 hunks)
  • packages/i18n/src/locales/ja/translations.json (1 hunks)
  • web/core/components/dropdowns/member/index.tsx (5 hunks)
  • web/core/components/issues/issue-modal/base.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/i18n/src/locales/en/translations.json
  • web/core/components/dropdowns/member/index.tsx
  • packages/i18n/src/locales/fr/translations.json
  • packages/i18n/src/locales/ja/translations.json
🔇 Additional comments (5)
web/core/components/issues/issue-modal/base.tsx (3)

6-6: LGTM: Translation hook setup is correct

The useTranslation hook is properly imported and initialized.

Also applies to: 58-58


220-221: Avoid string concatenation in translated success messages

The success message still uses string concatenation which can lead to grammatically incorrect sentences in non-English languages where word order might differ.

Replace with a single translation key:

- message: `${is_draft_issue ? t("draft_created") : t("issue_created_successfully")} `,
+ message: t(is_draft_issue ? "message.draft_created" : "message.issue_created_successfully"),

289-290: LGTM: Proper translation implementation

The success and error messages in the update flow correctly use direct translation keys without string concatenation.

Also applies to: 302-303

packages/i18n/src/locales/es/translations.json (2)

270-270: Use consistent translation for workspace terms

The workspace name translation is inconsistent with other occurrences:

-  "workspace_name": "nombre-del-espacio-de-trabajo",
+  "workspace_name": "Nombre del espacio de trabajo"

310-311: Add Spanish date format localization

For proper date localization in Spanish format (DD/MM/YYYY), add the following:

+  "date_format": "DD/MM/YYYY",
+  "time_format": "HH:mm",
   "start_date": "Fecha de inicio",
   "due_date": "Fecha de vencimiento"

packages/i18n/src/locales/es/translations.json Outdated Show resolved Hide resolved
packages/i18n/src/locales/es/translations.json Outdated Show resolved Hide resolved
@mathalav55 mathalav55 marked this pull request as ready for review December 18, 2024 08:56
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/i18n/src/locales/es/translations.json (2)

143-143: Improve translation of metaphorical expression

The translation of "10,000 feet view" is too literal and might not convey the intended meaning in Spanish.

Consider using a more culturally appropriate expression:

-  "10000_feet_view": "Vista de 10,000 pies de todos los ciclos activos.",
-  "10000_feet_view_description": "Amplía para ver ciclos en ejecución en todos tus proyectos a la vez en lugar de ir de ciclo en ciclo en cada proyecto.",
+  "10000_feet_view": "Vista general de todos los ciclos activos",
+  "10000_feet_view_description": "Obtén una perspectiva global de los ciclos en ejecución en todos tus proyectos a la vez.",

Also applies to: 144-144


317-318: Add missing ellipsis character

The loading text uses regular periods instead of the proper ellipsis character.

Apply this diff to use the proper ellipsis character:

-  "loading_members": "Cargando miembros..."
+  "loading_members": "Cargando miembros…"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd5b829 and 7c4d548.

📒 Files selected for processing (1)
  • packages/i18n/src/locales/es/translations.json (1 hunks)
🔇 Additional comments (2)
packages/i18n/src/locales/es/translations.json (2)

1-318: Verify translations with native speakers

While most translations appear correct, it's recommended to have a native Spanish speaker review the translations to ensure they are contextually accurate and maintain consistent formality levels throughout the file.

Run the following script to identify potential inconsistencies in formality levels:

✅ Verification successful

Based on the script results, I can now provide a final response:

Spanish translations maintain consistent informal tone

The translations consistently use the informal "tú" form throughout the interface, which is the preferred approach for modern Spanish software localization. The few instances of "su/sus" found are not related to formal pronouns but rather possessive adjectives in proper context (e.g., "su estado" meaning "its state").

The informal tone is appropriately maintained across:

  • User account sections ("Tu cuenta", "Tu trabajo")
  • Action prompts ("Selecciona tu tema", "Personaliza tu tema")
  • Workspace management ("Crea tu espacio de trabajo")
  • System messages and descriptions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for mixed formal/informal pronouns and conjugations

# Check for mixed use of "tú" vs "usted" forms
echo "Checking for mixed formal/informal pronouns:"
rg -i '\b(tu|tus|tuyo|tuya|tuyos|tuyas)\b' packages/i18n/src/locales/es/translations.json
echo "---"
rg -i '\b(usted|ustedes|su|sus|suyo|suya|suyos|suyas)\b' packages/i18n/src/locales/es/translations.json

Length of output: 2497


310-311: 🛠️ Refactor suggestion

Add date format localization

The date-related translations should include format strings to ensure proper localization for Spanish users.

Add the following translations:

+  "date_format": "DD/MM/YYYY",
+  "time_format": "HH:mm",
   "start_date": "Fecha de inicio",
   "due_date": "Fecha de vencimiento",

Likely invalid or redundant comment.

Comment on lines +46 to +47
"workspaces": "Espacios de trabajo",
"create_workspace": "Crear espacio de trabajo",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent translation of "workspace" terms

The translation of "workspace" is inconsistent:

  • Lines 46-47: Correctly translated as "Espacios de trabajo"
  • Line 270: Incorrectly using a URL-like format "nombre-del-espacio-de-trabajo"

Apply this diff to maintain consistency:

-  "workspace_name": "nombre-del-espacio-de-trabajo",
+  "workspace_name": "Nombre del espacio de trabajo",

Also applies to: 270-270

Comment on lines +261 to +264
"we_see_that_someone_has_invited_you_to_join_a_workspace": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
"join_a_workspace": "Unirse a un espacio de trabajo",
"we_see_that_someone_has_invited_you_to_join_a_workspace_description": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
"join_a_workspace_description": "Unirse a un espacio de trabajo",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate translations

These entries have identical translations which could lead to confusion:

  • "we_see_that_someone_has_invited_you_to_join_a_workspace" and its description
  • "join_a_workspace" and its description

Apply this diff to differentiate the descriptions:

   "we_see_that_someone_has_invited_you_to_join_a_workspace": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
-  "we_see_that_someone_has_invited_you_to_join_a_workspace_description": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
+  "we_see_that_someone_has_invited_you_to_join_a_workspace_description": "Has recibido una invitación para colaborar en un espacio de trabajo",
   "join_a_workspace": "Unirse a un espacio de trabajo",
-  "join_a_workspace_description": "Unirse a un espacio de trabajo",
+  "join_a_workspace_description": "Únete a un espacio de trabajo existente para colaborar con otros",
📝 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.

Suggested change
"we_see_that_someone_has_invited_you_to_join_a_workspace": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
"join_a_workspace": "Unirse a un espacio de trabajo",
"we_see_that_someone_has_invited_you_to_join_a_workspace_description": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
"join_a_workspace_description": "Unirse a un espacio de trabajo",
"we_see_that_someone_has_invited_you_to_join_a_workspace": "Vemos que alguien te ha invitado a unirte a un espacio de trabajo",
"join_a_workspace": "Unirse a un espacio de trabajo",
"we_see_that_someone_has_invited_you_to_join_a_workspace_description": "Has recibido una invitación para colaborar en un espacio de trabajo",
"join_a_workspace_description": "Únete a un espacio de trabajo existente para colaborar con otros",

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

Successfully merging this pull request may close these issues.

7 participants