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-3165]improvement: added translation to issues - lists, headers #6417

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

Conversation

mathalav55
Copy link
Collaborator

@mathalav55 mathalav55 commented Jan 17, 2025

Description

Added language support for issues lists and headers.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

References

WEB-3165

Summary by CodeRabbit

Release Notes

  • Internationalization

    • Added comprehensive translation support for multiple languages (English, Spanish, French, Japanese, Chinese)
    • Expanded translation keys for issues, layouts, filters, and user interface elements
    • Simplified "Custom theme" to "Custom" across locales
    • Enhanced localization for error messages, success notifications, and user interactions
  • Localization Improvements

    • Updated translation files with new keys for project management terminology
    • Added support for dynamic text translation in various components
    • Implemented translation hooks across web application components
  • User Interface

    • Replaced hardcoded strings with translatable keys
    • Improved multi-language support for buttons, labels, and messages

@mathalav55 mathalav55 added 🌟enhancement New feature or request 🌐frontend labels Jan 17, 2025
@mathalav55 mathalav55 added this to the v0.24.2 milestone Jan 17, 2025
@mathalav55 mathalav55 self-assigned this Jan 17, 2025
Copy link

makeplane bot commented Jan 17, 2025

Pull Request Linked with Plane Issues

Comment Automatically Generated by Plane

4 similar comments
Copy link

makeplane bot commented Jan 17, 2025

Pull Request Linked with Plane Issues

Comment Automatically Generated by Plane

Copy link

makeplane bot commented Jan 17, 2025

Pull Request Linked with Plane Issues

Comment Automatically Generated by Plane

Copy link

makeplane bot commented Jan 17, 2025

Pull Request Linked with Plane Issues

Comment Automatically Generated by Plane

Copy link

makeplane bot commented Jan 17, 2025

Pull Request Linked with Plane Issues

Comment Automatically Generated by Plane

Copy link
Contributor

coderabbitai bot commented Jan 17, 2025

Walkthrough

This pull request introduces comprehensive internationalization (i18n) support across multiple components and translation files. The changes primarily focus on adding translation keys to various JSON files for different languages (English, Spanish, French, Japanese, and Chinese), and integrating the useTranslation hook from the @plane/i18n package into numerous React components. The modifications enable dynamic text translation, making the application more accessible to users speaking different languages.

Changes

File Change Summary
packages/i18n/src/locales/*/translations.json Added numerous translation keys for issues, layouts, filters, actions, and error messages across multiple languages
web/core/components/* Integrated useTranslation hook to replace hardcoded strings with translatable keys
web/core/constants/issue.ts Added titleTranslationKey to various constant objects
web/core/constants/filters.ts Added nameTranslationKey to date filter options

Possibly related PRs

Suggested Reviewers

  • rahulramesha
  • sriramveeraghanta

Poem

🐰 A Rabbit's Localization Ballad 🌍

Translations hop from shore to shore,
Words dancing through each language's door
Strings no longer static and plain
Now speak in every tongue's refrain
Internationalization's delight! 🌈


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: 11

🔭 Outside diff range comments (5)
web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx (1)

Line range hint 44-44: Inconsistent translation pattern for subGroupBy titles.

The title prop is using the hardcoded subGroupBy.title instead of following the translation pattern used in other components (t(subGroupBy.titleTranslationKey)).

Apply this diff to maintain consistency:

-                title={subGroupBy.title}
+                title={t(subGroupBy.titleTranslationKey)}
web/core/components/project/dropdowns/filters/created-at.tsx (1)

Line range hint 47-47: Add translation for "Created date" title

The title in DateFilterModal is still hardcoded and needs to be translated.

-          title="Created date"
+          title={t("created_date")}
web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx (1)

Line range hint 68-87: Fix fragment key and optimize onClick handler

There are two issues in this code segment:

  1. The fragment wrapper in the map function is missing a key prop
  2. The onClick handler creates a new function on every render
-          {filteredDisplayProperties.map((displayProperty) => (
-            <>
+          {filteredDisplayProperties.map((displayProperty) => (
+            <React.Fragment key={displayProperty.key}>
               <button
-                key={displayProperty.key}
                 type="button"
                 className={`rounded border px-2 py-0.5 text-xs transition-all ${
                   displayProperties?.[displayProperty.key]
                     ? "border-custom-primary-100 bg-custom-primary-100 text-white"
                     : "border-custom-border-200 hover:bg-custom-background-80"
                 }`}
-                onClick={() =>
-                  handleUpdate({
-                    [displayProperty.key]: !displayProperties?.[displayProperty.key],
-                  })
-                }
+                onClick={handleUpdate.bind(null, {
+                  [displayProperty.key]: !displayProperties?.[displayProperty.key],
+                })}
               >
                 {t(displayProperty.titleTranslationKey)}
               </button>
-            </>
+            </React.Fragment>
           ))}
web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx (1)

Line range hint 93-94: Fix inconsistent translation usage for view toggles.

The "View less"/"View all" strings are hardcoded while other components use translation keys (t("view_less")/t("view_all")).

Apply this diff to maintain consistency:

-                    {itemsToRender === sortedOptions.length ? "View less" : "View all"}
+                    {itemsToRender === sortedOptions.length ? t("view_less") : t("view_all")}
web/core/components/issues/issue-detail/issue-activity/root.tsx (1)

Line range hint 142-155: Improve error handling in uploadCommentAsset

The error handling in uploadCommentAsset is inconsistent with other operations. It logs to console and throws a different error format.

 uploadCommentAsset: async (file, commentId) => {
   try {
     if (!workspaceSlug || !projectId) throw new Error(t("missing_fields"));
     const res = await fileService.uploadProjectAsset(
       workspaceSlug,
       projectId,
       {
         entity_identifier: commentId ?? "",
         entity_type: EFileAssetType.COMMENT_DESCRIPTION,
       },
       file
     );
     return res;
   } catch (error) {
-    console.log("Error in uploading comment asset:", error);
-    throw new Error(t("asset_upload_failed_please_try_again_later"));
+    setToast({
+      title: t("error"),
+      type: TOAST_TYPE.ERROR,
+      message: t("asset_upload_failed_please_try_again_later"),
+    });
+    throw error;
   }
 },
🧹 Nitpick comments (37)
web/core/components/issues/peek-overview/root.tsx (2)

117-119: Consider translating all error messages consistently.

While the error messages for issue deletion and restoration are properly translated, there are other error messages in the file that still use hardcoded strings. For consistency, consider translating these messages as well:

  • Line 191: "Issue could not be added to the cycle. Please try again."
  • Line 220: "Issue could not be added to the cycle. Please try again."
  • Lines 245-247: Error messages in setPromiseToast
  • Lines 285-287: Error messages in setPromiseToast

Also applies to: 161-162


150-151: Consider translating all success messages consistently.

While the success message for issue restoration is properly translated, there are other success messages in the file that still use hardcoded strings. For consistency, consider translating these messages as well:

  • Lines 245-247: Success messages in setPromiseToast
  • Lines 285-287: Success messages in setPromiseToast
web/core/components/issues/issue-layouts/quick-add/root.tsx (1)

171-171: Simplify boolean expression and use optional chaining.

The current boolean expression can be simplified for better readability.

-hasError={errors && errors?.name && errors?.name?.message ? true : false}
+hasError={Boolean(errors?.name?.message)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 171-171: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 171-171: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx (1)

16-16: Consider using a single translation key for better language support.

Instead of concatenating translated strings, use a single translation key with interpolation to better support languages with different word orders.

-      <span className="text-sm font-medium">{`${t("new")} ${isEpic ? t("epic") : t("issue")}`}</span>
+      <span className="text-sm font-medium">
+        {t(isEpic ? "new_epic" : "new_issue")}
+      </span>
web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx (1)

Line range hint 1-22: Consider consolidating duplicate button components.

All four quick-add button components (Kanban, List, Spreadsheet, and Gantt) share nearly identical implementation, differing only in minor styling. Consider creating a single base component that accepts a variant prop to handle the styling differences.

Example approach:

type ButtonVariant = 'kanban' | 'list' | 'spreadsheet' | 'gantt';

interface QuickAddIssueButtonProps extends TQuickAddIssueButton {
  variant: ButtonVariant;
}

const variantStyles: Record<ButtonVariant, string> = {
  kanban: "py-1.5",
  list: "py-3",
  spreadsheet: "px-2 pt-3",
  gantt: "py-2"
};

export const QuickAddIssueButton: FC<QuickAddIssueButtonProps> = observer((props) => {
  const { onClick, isEpic = false, variant } = props;
  const { t } = useTranslation();

  return (
    <button
      type="button"
      className={cn(
        "flex items-center gap-2 text-custom-text-350 hover:text-custom-text-300",
        variantStyles[variant]
      )}
      onClick={onClick}
    >
      <PlusIcon className="h-3.5 w-3.5 stroke-2" />
      <span className="text-sm font-medium">
        {t(isEpic ? "new_epic" : "new_issue")}
      </span>
    </button>
  );
});
web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(list)/page.tsx (1)

24-24: Consider DRY principle for title construction

The same title construction ${project?.name} - ${t("issues")} is duplicated in both the pageTitle variable and the title element. Consider extracting this into a constant to follow DRY principles.

  const { t } = useTranslation();
+ const constructedTitle = project?.name ? `${project.name} - ${t("issues")}` : undefined;
- const pageTitle = project?.name ? `${project?.name} - ${t("issues")}` : undefined;

  return (
    <>
-     <PageHead title={pageTitle} />
+     <PageHead title={constructedTitle} />
      <Head>
-       <title>
-         {project?.name} - {t("issues")}
-       </title>
+       <title>{constructedTitle}</title>
      </Head>

Also applies to: 30-32

web/core/components/issues/issue-layouts/save-filter-view.tsx (1)

36-38: Consider adding aria-label for better accessibility

The translation implementation looks good. Consider adding an aria-label to improve accessibility.

-     <Button size="sm" onClick={() => setViewModal(true)}>
+     <Button 
+       size="sm" 
+       onClick={() => setViewModal(true)} 
+       aria-label={t("save_view")}
+     >
        {t("save_view")}
      </Button>
web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx (1)

3-3: LGTM with a suggestion for type safety.

The translation implementation is correct, but we could enhance type safety.

Consider adding type checking for translation keys:

// Add to your types file
type TranslationKey = keyof typeof import('@plane/i18n').translations.en;

// Update the option type
interface IssueExtraOption {
  key: TIssueExtraOptions;
  titleTranslationKey: TranslationKey;
}

Also applies to: 23-23, 37-37

web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx (1)

3-3: LGTM with a DRY principle suggestion.

The translation implementation is correct but duplicates logic from spreadsheet.tsx.

Consider extracting common translation logic into a shared hook:

// hooks/useIssueFormTranslations.ts
export const useIssueFormTranslations = (isEpic: boolean) => {
  const { t } = useTranslation();
  return {
    placeholder: isEpic ? t("epic_title") : t("issue_title"),
    requiredMessage: `${isEpic ? t("epic") : t("issue")} ${t("title_is_required")}.`,
  };
};

This would reduce duplication across different form components (calendar, spreadsheet, etc.).

Also applies to: 8-8, 24-24, 26-26

web/core/components/issues/issue-layouts/quick-add/form/list.tsx (1)

29-29: Consider simplifying the template literal.

The translation string looks good, but the template literal could be simplified by moving the entire string into a single translation key.

Instead of:

`${t("press_enter_to_add_another")} ${isEpic ? t("epic") : t("issue")}`

Consider adding a translation key like:

t(isEpic ? "press_enter_to_add_another_epic" : "press_enter_to_add_another_issue")

This would make translations more natural in languages with different word orders.

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

4-4: Consider using more semantic translation keys.

The translation keys are directly derived from the English text (e.g., "1_week_from_now"). Consider using more semantic keys that describe the meaning rather than the text.

Example:

-    nameTranslationKey: "1_week_from_now",
+    nameTranslationKey: "date_filter.future.one_week",

This makes the translation system more maintainable and less tied to specific text.

Also applies to: 9-9, 14-14, 19-19, 27-27, 32-32, 37-37

web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx (2)

30-30: Consider using a single translation key for the title.

The current implementation concatenates multiple translated strings, which might not work well for all languages due to different word orders.

Instead of:

`${isEpic ? t("epic") : t("issue")} ${t("grouping")}`

Consider:

t(isEpic ? "epic_grouping_title" : "issue_grouping_title")

41-41: Simplify the translation string composition.

Similar to the title, the option text combines multiple translations which could lead to grammatical issues in some languages.

Instead of:

`${t(issueType?.titleTranslationKey)} ${isEpic ? t("epics") : t("issues")}`

Consider:

t(isEpic ? `epic_group_by_${issueType?.titleTranslationKey}` : `issue_group_by_${issueType?.titleTranslationKey}`)
web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx (1)

24-24: Consider simplifying the template string.

The translation can be simplified by using a single translation key for the full message instead of composing it from multiple parts.

Instead of:

`${isEpic ? t("epic") : t("issue")} ${t("title_is_required")}.`

Consider adding translation keys like:

t(isEpic ? "epic_title_required" : "issue_title_required")

This approach is more maintainable as it allows translators to handle the full sentence structure according to their language's grammar rules.

web/core/components/core/filters/date-filter-select.tsx (1)

50-51: Reduce code duplication in translation key access.

The pattern for accessing and translating the date range item is duplicated. Consider extracting it to a helper function.

const getTranslatedOption = (value: string) => {
  const option = dueDateRange.find((item) => item.value === value);
  return option ? `${title} ${t(option.nameTranslationKey)}` : t("select_date");
};

Then use it like:

<span>{getTranslatedOption(value)}</span>

Also applies to: 59-61

web/core/components/issues/create-issue-toast-action-items.tsx (1)

54-54: Optimize complex string interpolation.

The current implementation concatenates multiple translated strings. Consider using a single translation key with interpolation for better maintainability and context for translators.

Instead of:

`${t("view")} ${isEpic ? t("epic") : t("issue")}`

Consider:

t("view_item", { item: isEpic ? t("epic") : t("issue") })

Add to translation file:

{
  "view_item": "View {{item}}"
}
web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx (1)

20-22: Remove unnecessary i18n comment.

The comment // i18n is redundant as the hook usage is self-documenting.

- // i18n
  const { t } = useTranslation();
web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx (1)

19-20: Remove unnecessary i18n comment.

The comment // i18n is redundant as the hook usage is self-documenting.

- // i18n
  const { t } = useTranslation();
web/core/components/issues/issue-layouts/filters/header/filters/target-date.tsx (2)

52-52: Consider using translation interpolation instead of string concatenation

Replace string concatenation with translation interpolation for better i18n practices.

-        title={`${t("target_date")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
+        title={t("target_date_with_count", { count: appliedFiltersCount })}

Line range hint 61-67: Remove unnecessary fragment wrapper in map function

The fragment wrapper is not needed since each mapped item is a single element.

-              {filteredOptions.map((option) => (
-                <FilterOption
-                  key={option.value}
-                  isChecked={appliedFilters?.includes(option.value) ? true : false}
-                  onClick={() => handleUpdate(option.value)}
-                  title={t(option.nameTranslationKey)}
-                  multiple
-                />
-              ))}
+              {filteredOptions.map((option) => 
+                <FilterOption
+                  key={option.value}
+                  isChecked={appliedFilters?.includes(option.value) ? true : false}
+                  onClick={() => handleUpdate(option.value)}
+                  title={t(option.nameTranslationKey)}
+                  multiple
+                />
+              )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 63-63: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx (1)

58-58: Fix extra space in title string interpolation.

The template literal has an extra space after ${t("label")} which could cause inconsistent spacing in different translations.

-        title={`${t("label")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
+        title={`${t("label")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
web/core/components/issues/issue-layouts/filters/header/filters/module.tsx (2)

57-57: Fix inconsistent spacing in title string interpolation.

The template literal has extra spaces that could cause inconsistent spacing in different translations.

-        title={`${t("module")} ${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
+        title={`${t("module")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}

Line range hint 68-74: Fix incorrect variable naming in map function.

The variable name 'cycle' is used in the map function but this component is for modules, which could cause confusion.

-                {sortedOptions.slice(0, itemsToRender).map((cycle) => (
+                {sortedOptions.slice(0, itemsToRender).map((module) => (
                   <FilterOption
-                    key={cycle.id}
-                    isChecked={appliedFilters?.includes(cycle.id) ? true : false}
-                    onClick={() => handleUpdate(cycle.id)}
+                    key={module.id}
+                    isChecked={appliedFilters?.includes(module.id) ? true : false}
+                    onClick={() => handleUpdate(module.id)}
                     icon={<DiceIcon className="h-3 w-3 flex-shrink-0" />}
-                    title={cycle.name}
+                    title={module.name}
                   />
                 ))}
web/core/components/issues/issue-layouts/filters/header/filters/project.tsx (1)

55-55: Fix inconsistent spacing in title string interpolation.

The template literal has extra spaces that could cause inconsistent spacing in different translations.

-        title={`${t("project")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
+        title={`${t("project")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx (3)

59-59: Fix inconsistent spacing in title string interpolation.

The template literal has extra spaces that could cause inconsistent spacing in different translations.

-        title={`${t("created_by")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
+        title={`${t("created_by")}${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}

Line range hint 73-79: Simplify boolean expression in isChecked prop.

The ternary operator returning a boolean can be simplified.

                    <FilterOption
                      key={`created-by-${member.id}`}
-                      isChecked={appliedFilters?.includes(member.id) ? true : false}
+                      isChecked={Boolean(appliedFilters?.includes(member.id))}
                      onClick={() => handleUpdate(member.id)}
                      icon={<Avatar name={member.display_name} src={getFileURL(member.avatar_url)} size="md" />}
                      title={currentUser?.id === member.id ? t("you") : member?.display_name}
                    />
🧰 Tools
🪛 Biome (1.9.4)

[error] 75-75: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


6-6: Overall i18n implementation looks good but needs standardization.

The internationalization implementation is consistent across all filter components. However, consider creating a utility function for formatting filter titles to ensure consistent spacing and reduce duplication. This would help maintain consistency as more filters are added.

Example utility function:

const formatFilterTitle = (key: string, count: number) => 
  `${t(key)}${count > 0 ? ` (${count})` : ""}`;

Then use it like:

title={formatFilterTitle("label", appliedFiltersCount)}

Also applies to: 6-6, 6-6, 7-7

web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx (1)

90-90: Consider handling plural forms for view_all/view_less translations.

The current implementation uses simple translation keys. Consider using plural forms if the translations might vary based on the number of items in different languages.

Also applies to: 95-95

web/core/components/dropdowns/module/module-options.tsx (1)

132-132: Consider improving type safety for displayValue prop.

The displayValue prop uses any type which could lead to type-safety issues.

-displayValue={(assigned: any) => assigned?.name}
+displayValue={(assigned: { name: string }) => assigned?.name}
web/core/components/issues/filters.tsx (1)

144-147: Consider adding ARIA label for better accessibility.

The analytics button could benefit from an ARIA label to improve screen reader support.

-<Button className="hidden md:block" onClick={() => setAnalyticsModal(true)} variant="neutral-primary" size="sm">
+<Button 
+  className="hidden md:block" 
+  onClick={() => setAnalyticsModal(true)} 
+  variant="neutral-primary" 
+  size="sm"
+  aria-label={t("open_project_analytics")}
+>
   {t("analytics")}
 </Button>
web/core/components/dropdowns/cycle/cycle-options.tsx (1)

169-169: Consider enhancing loading state feedback

The loading state could be improved by adding a loading spinner or skeleton component alongside the loading text for better user experience.

web/core/components/core/filters/date-filter-modal.tsx (1)

141-145: Consider date localization

While the text is properly translated, consider using a date formatting library that supports localization (e.g., Intl.DateTimeFormat) for the rendered dates to ensure they follow the user's locale conventions.

-      <span>{renderFormattedDate(watch("date1"))}</span>
+      <span>{new Intl.DateTimeFormat(i18n.language).format(watch("date1"))}</span>
-      {!isInvalid && <span>{renderFormattedDate(watch("date2"))}</span>}
+      {!isInvalid && <span>{new Intl.DateTimeFormat(i18n.language).format(watch("date2"))}</span>}
web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(list)/mobile-header.tsx (1)

109-113: Enhance accessibility for layout selection

Add ARIA labels to improve screen reader support for the layout selection menu.

 <div className="flex flex-start text-sm text-custom-text-200">
   {t("layout")}
-  <ChevronDown className="ml-2  h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
+  <ChevronDown 
+    className="ml-2 h-4 w-4 text-custom-text-200 my-auto" 
+    strokeWidth={2}
+    aria-hidden="true"
+  />
 </div>
web/core/constants/issue.ts (2)

51-63: Consider using dot notation for hierarchical translation keys.

While the current implementation works, consider using dot notation (e.g., state.groups instead of state_groups) for better organization and maintainability of translation keys.


144-183: Consider consolidating layout-related translation keys.

The layout mapping includes both titleTranslationKey and labelTranslationKey. Consider:

  1. Using a single translation key if the title and label are always the same
  2. Using a consistent prefix for layout-related keys
packages/i18n/src/locales/en/translations.json (1)

319-396: Ensure consistent capitalization in translations.

Some translations have inconsistent capitalization:

  • "Sub issue count" vs. "Sub-group by"
  • "Last created" vs. "Last Updated"

Consider standardizing the capitalization rules.

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

319-319: Fix capitalization in French translation.

The translation for "inbox" should be capitalized as it's used as a UI element name.

-  "inbox": "Boîte de réception",
+  "inbox": "Boîte de Réception",
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 95f43a7 and e7d3ae9.

📒 Files selected for processing (60)
  • packages/i18n/src/locales/en/translations.json (2 hunks)
  • packages/i18n/src/locales/es/translations.json (2 hunks)
  • packages/i18n/src/locales/fr/translations.json (2 hunks)
  • packages/i18n/src/locales/ja/translations.json (2 hunks)
  • web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(detail)/header.tsx (3 hunks)
  • web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(list)/mobile-header.tsx (6 hunks)
  • web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(list)/page.tsx (2 hunks)
  • web/ce/components/issues/header.tsx (5 hunks)
  • web/ce/components/issues/worklog/activity/filter-root.tsx (1 hunks)
  • web/ce/constants/issues.ts (1 hunks)
  • web/core/components/core/filters/date-filter-modal.tsx (4 hunks)
  • web/core/components/core/filters/date-filter-select.tsx (3 hunks)
  • web/core/components/dropdowns/cycle/cycle-options.tsx (5 hunks)
  • web/core/components/dropdowns/cycle/index.tsx (3 hunks)
  • web/core/components/dropdowns/module/index.tsx (7 hunks)
  • web/core/components/dropdowns/module/module-options.tsx (5 hunks)
  • web/core/components/dropdowns/state.tsx (1 hunks)
  • web/core/components/issues/create-issue-toast-action-items.tsx (3 hunks)
  • web/core/components/issues/filters.tsx (5 hunks)
  • web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx (4 hunks)
  • web/core/components/issues/issue-detail/issue-activity/root.tsx (5 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx (5 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx (5 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx (5 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/module.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/project.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/state.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/target-date.tsx (4 hunks)
  • web/core/components/issues/issue-layouts/filters/header/layout-selection.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/quick-add/button/list.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/list.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/root.tsx (6 hunks)
  • web/core/components/issues/issue-layouts/save-filter-view.tsx (3 hunks)
  • web/core/components/issues/issue-modal/form.tsx (1 hunks)
  • web/core/components/issues/parent-issues-list-modal.tsx (4 hunks)
  • web/core/components/issues/peek-overview/root.tsx (5 hunks)
  • web/core/components/project/applied-filters/date.tsx (2 hunks)
  • web/core/components/project/dropdowns/filters/created-at.tsx (3 hunks)
  • web/core/constants/filters.ts (2 hunks)
  • web/core/constants/issue.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
web/core/components/issues/issue-layouts/quick-add/root.tsx

[error] 171-171: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 171-171: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (43)
web/core/components/issues/peek-overview/root.tsx (1)

8-8: LGTM! Translation hook properly integrated.

The useTranslation hook is correctly imported and initialized.

Also applies to: 41-42

web/core/components/issues/issue-layouts/quick-add/root.tsx (3)

10-10: LGTM! Import added correctly.

The useTranslation hook import is properly placed and necessary for internationalization support.


70-71: LGTM! Translation hook setup is correct.

The useTranslation hook is properly initialized and the t function is correctly destructured.


166-177: LGTM! Form rendering and translations look good.

The form component props are properly passed and the text translations are correctly implemented using template literals.

Also applies to: 188-188

🧰 Tools
🪛 Biome (1.9.4)

[error] 171-171: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 171-171: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

web/core/components/issues/issue-layouts/quick-add/button/list.tsx (1)

17-17: Same translation concatenation pattern as in kanban.tsx.

This component uses the same string concatenation pattern. Please apply the same improvement suggested for the KanbanQuickAddIssueButton component.

web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx (1)

18-18: Same translation concatenation pattern as in previous components.

This component uses the same string concatenation pattern. Please apply the same improvement suggested for the previous components.

web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx (1)

19-19: Same translation concatenation pattern as in previous components.

This component uses the same string concatenation pattern. Please apply the same improvement suggested for the previous components.

web/ce/components/issues/worklog/activity/filter-root.tsx (1)

24-24: LGTM! Good separation of concerns

The addition of labelTranslationKey properly separates the translation key from the default label, following i18n best practices.

web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx (1)

3-3: LGTM! Translation implementation looks good.

The changes correctly implement i18n support by:

  • Adding the useTranslation hook
  • Replacing all hardcoded strings with translation keys
  • Using consistent string interpolation for dynamic content

To ensure all translation keys are properly defined, run:

Also applies to: 8-8, 20-20, 22-22, 28-28

✅ Verification successful

Translation keys verified successfully

All required translation keys are properly defined in the English locale file:

  • Title validation
  • Add another prompt
  • Epic/Issue titles
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if all used translation keys exist in the English locale file
rg -q "epic_title|issue_title|title_is_required|press_enter_to_add_another|epic|issue" "packages/i18n/src/locales/en/"

Length of output: 118


Script:

#!/bin/bash
# First find the English locale files
fd -t f . "packages/i18n/src/locales/en"

# Then search for the specific keys with context
rg -A 2 "epic_title|issue_title|title_is_required|press_enter_to_add_another|epic|issue" "packages/i18n/src/locales/en/"

Length of output: 9493

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

10-20: Well-structured i18n support in constants.

The changes properly extend the type system to support translations:

  • Added labelTranslationKey to activity filter options
  • Updated TActivityFilterOption type definition
  • Maintained type safety while adding i18n support

Also applies to: 27-27

web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx (1)

20-21: LGTM! Clean i18n integration.

The translation hook is properly initialized and the implementation follows React best practices by declaring hooks at the top level.

web/core/components/project/applied-filters/date.tsx (1)

Line range hint 21-36: LGTM! Well-structured date label handling.

The implementation nicely handles both translated labels and custom date formatting with proper fallbacks.

web/core/components/issues/issue-layouts/filters/header/layout-selection.tsx (2)

35-35: LGTM! Clean tooltip translation implementation.

The translation implementation for tooltips is clean and follows best practices.


Line range hint 3-3: Verify translation key coverage.

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

Also applies to: 7-7, 24-24, 35-35

web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx (2)

6-6: LGTM! Clean integration of i18n support.

The useTranslation hook is properly imported and initialized.

Also applies to: 25-26


37-37: Verify translation keys exist in locale files.

Please ensure that the following translation keys are defined in all supported locale files:

  • priority
  • Priority-related keys referenced by priority.titleTranslationKey
  • no_matches_found

Also applies to: 50-50, 54-54

✅ Verification successful

All translation keys verified successfully

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify translation keys exist in locale files
# Expected: All required keys should be present in all locale files

# Check for required translation keys
rg -l '"priority":|"no_matches_found":' packages/i18n/src/locales/*/translations.json

# Check for priority-related translation keys
ast-grep --pattern 'titleTranslationKey: "$_"' web/core/constants/issue.ts | \
  xargs -I {} rg -l "{}" packages/i18n/src/locales/*/translations.json

Length of output: 859


Script:

#!/bin/bash
# Show the actual content around priority keys
echo "=== Priority translations ==="
rg -A 1 '"priority":' packages/i18n/src/locales/*/translations.json

# Check the content of issue.ts for priority-related constants
echo -e "\n=== Priority-related constants ==="
cat web/core/constants/issue.ts

# Show content around no_matches_found
echo -e "\n=== No matches found translations ==="
rg -A 1 '"no_matches_found":' packages/i18n/src/locales/*/translations.json

Length of output: 19545


Script:

#!/bin/bash
# Check for priority level translations
echo "=== Priority level translations ==="
rg -A 1 '"urgent":|"high":|"medium":|"low":|"none":' packages/i18n/src/locales/*/translations.json

Length of output: 2383

web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx (1)

3-3: LGTM! Consistent i18n implementation.

The translation implementation follows the established pattern and maintains consistency with other components.

Also applies to: 21-21, 31-31, 51-51

web/core/components/issues/create-issue-toast-action-items.tsx (1)

59-59: LGTM! Clear and consistent translations.

The translation of "copied" and "copy_link" strings is implemented correctly.

Also applies to: 67-67

web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/issues/(detail)/header.tsx (1)

6-6: LGTM! Clean i18n implementation.

The translation implementation follows best practices with proper hook usage and simple, clear translation keys.

Also applies to: 18-18, 42-42

web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx (1)

42-42: LGTM! Consistent translation implementation.

The translation keys are well-structured and consistently applied across the component.

Also applies to: 65-65, 70-70

web/core/components/issues/issue-layouts/filters/header/filters/state.tsx (1)

Line range hint 63-63: Consider translating state names

State names are currently displayed without translation. Consider adding translations for state names if they should be localized.

web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx (1)

7-7: LGTM! Clean and consistent implementation.

The translation implementation follows the established pattern and maintains consistency with other filter components.

Also applies to: 24-25, 59-59, 85-85, 95-95, 100-100

web/ce/components/issues/header.tsx (1)

110-111: LGTM! Clean implementation of button text translation.

The translation of the "Add Issue" button text is well-implemented, maintaining the existing layout while properly handling translations.

web/core/components/dropdowns/cycle/index.tsx (1)

6-6: LGTM! Clean i18n implementation.

The translation integration is properly implemented with a clear key naming convention.

Also applies to: 56-57, 113-113

web/core/components/dropdowns/module/module-options.tsx (1)

11-11: LGTM! Comprehensive i18n implementation.

All user-facing strings have been properly internationalized with consistent key naming.

Also applies to: 39-40, 103-103, 107-107, 131-131, 163-163, 166-166

web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (1)

3-3: LGTM! Clean i18n implementation.

The translation integration is properly implemented with consistent key naming.

Also applies to: 51-53, 163-163

web/core/components/issues/filters.tsx (1)

8-8: LGTM! Comprehensive i18n implementation.

All user-facing strings have been properly internationalized with consistent key naming.

Also applies to: 38-38, 116-116, 132-132, 146-146

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

225-225: LGTM! Translation key properly implemented.

The search placeholder text has been correctly internationalized using the translation function.

web/core/components/issues/parent-issues-list-modal.tsx (1)

127-127: LGTM! All text strings properly internationalized.

The search-related text strings have been correctly converted to use translation keys, maintaining a consistent pattern across the modal interface.

Also applies to: 140-140, 146-146

web/core/components/dropdowns/module/index.tsx (1)

90-90: LGTM! Comprehensive internationalization with proper plural handling.

All text strings have been properly internationalized. Notable implementation of plural forms for module count using conditional translation keys (module/modules).

Also applies to: 110-110, 121-121, 265-265

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (1)

101-101: LGTM! Consistent translation implementation.

The search placeholder translation matches the pattern used in other search components, maintaining consistency across the application.

web/core/constants/issue.ts (4)

39-45: LGTM! Translation keys for issue priorities are well-structured.

The translation keys are concise and match the priority values, making them easy to maintain and understand.


69-76: LGTM! Translation keys for order options are clear and descriptive.

The translation keys effectively represent the sorting options and their meanings.


82-86: LGTM! Filter options translation keys are consistent.

The translation keys for filter options follow a simple and clear pattern.


137-140: LGTM! Extra options translation keys are descriptive.

The translation keys clearly describe their purpose and are easy to understand.

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

542-542: LGTM! Button text now uses translation.

The hardcoded string has been correctly replaced with the translation key.

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

76-76: LGTM! Simplified translation for "custom".

The translation has been simplified from "カスタムテーマ" to "カスタム", which is more versatile for general use.


319-396: Verify consistency of date-related translations.

The translations for date-related terms (e.g., "1_week_ago", "2_weeks_ago") should be reviewed for natural expression in Japanese.

✅ Verification successful

Date-related translations are correctly implemented in Japanese

The translations use proper Japanese counters (週間, ヶ月) and time markers (前, 後) consistently, following natural Japanese language conventions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Compare date-related translations between English and Japanese
# Expected: All date-related keys should have appropriate translations

echo "Checking date-related translations:"
for key in "1_week_ago" "2_weeks_ago" "1_month_ago" "2_months_ago" "1_week_from_now" "2_weeks_from_now" "1_month_from_now" "2_months_from_now"; do
  echo "\nKey: $key"
  echo "English:"
  rg "\"$key\":" packages/i18n/src/locales/en/translations.json
  echo "Japanese:"
  rg "\"$key\":" packages/i18n/src/locales/ja/translations.json
done

Length of output: 3732

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

77-77: LGTM! Simplified translation for "custom".

The translation has been simplified from "Custom theme" to "Custom", making it more versatile for general use.

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

76-76: LGTM! Translation improvement for "custom".

The change from "Tema personalizado" to "Personalizado" makes the translation more versatile while maintaining clarity.


319-396: LGTM! Comprehensive and well-structured translations.

The new translations:

  • Use appropriate Spanish technical terminology
  • Maintain consistent formality level
  • Follow natural Spanish language patterns
  • Properly handle UI/UX terminology
packages/i18n/src/locales/fr/translations.json (2)

76-76: LGTM! Translation improvement for "custom".

The change from "Thème personnalisé" to "Personnalisé" makes the translation more versatile while maintaining clarity.


319-396: LGTM! Comprehensive and well-structured translations.

The new translations:

  • Use appropriate French technical terminology
  • Maintain consistent formality level
  • Follow natural French language patterns
  • Properly handle UI/UX terminology
  • Correctly implement French typography rules

@mathalav55 mathalav55 marked this pull request as draft January 17, 2025 07:33
* imoprovement: added chinese translations
@mathalav55 mathalav55 marked this pull request as ready for review January 17, 2025 12:14
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

🧹 Nitpick comments (2)
web/core/components/core/filters/date-filter-select.tsx (1)

23-39: Consider using more specific translation keys.

The translation keys currently mirror the English names, which might lead to confusion and maintenance issues. Consider using more specific keys that follow a hierarchical structure.

 const dueDateRange: DueDate[] = [
   {
-    nameTranslationKey: "before",
+    nameTranslationKey: "date_filter.before",
     name: "before",
     value: "before",
     icon: <CalendarBeforeIcon className="h-4 w-4" />,
   },
   {
-    nameTranslationKey: "after",
+    nameTranslationKey: "date_filter.after",
     name: "after",
     value: "after",
     icon: <CalendarAfterIcon className="h-4 w-4" />,
   },
   {
-    nameTranslationKey: "range",
+    nameTranslationKey: "date_filter.range",
     name: "range",
     value: "range",
     icon: <CalendarDays className="h-4 w-4" />,
   },
 ];
packages/i18n/src/locales/fr/translations.json (1)

323-329: Maintain consistency in layout terminology.

The translations for layout types are good, but consider standardizing the term "disposition" usage:

  • "Disposition de liste"
  • "Disposition de tableau" (used twice for both "board" and "table")

Consider using "tableau de bord" for "board_layout" to differentiate it from "table_layout":

-  "board_layout": "Disposition de tableau",
+  "board_layout": "Disposition de tableau de bord",
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e7d3ae9 and 937919e.

📒 Files selected for processing (13)
  • packages/i18n/src/locales/en/translations.json (2 hunks)
  • packages/i18n/src/locales/es/translations.json (2 hunks)
  • packages/i18n/src/locales/fr/translations.json (2 hunks)
  • packages/i18n/src/locales/ja/translations.json (2 hunks)
  • packages/i18n/src/locales/zh-CN/translations.json (2 hunks)
  • web/ce/components/issues/header.tsx (5 hunks)
  • web/core/components/core/filters/date-filter-select.tsx (2 hunks)
  • web/core/components/issues/create-issue-toast-action-items.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/list.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/quick-add/root.tsx (5 hunks)
  • web/core/components/issues/peek-overview/root.tsx (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • web/core/components/issues/create-issue-toast-action-items.tsx
  • web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx
  • web/core/components/issues/peek-overview/root.tsx
  • web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx
  • web/ce/components/issues/header.tsx
  • web/core/components/issues/issue-layouts/quick-add/form/list.tsx
🔇 Additional comments (14)
web/core/components/core/filters/date-filter-select.tsx (3)

5-5: LGTM! Import of translation hook.

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


15-15: LGTM! Type definition enhancement.

The addition of nameTranslationKey to the DueDate type properly enforces type safety for translations.


61-61: 🛠️ Refactor suggestion

Add fallback for missing translation keys in options list.

Similar to the label implementation, add a fallback for missing translation keys in the options list to maintain consistency and prevent potential rendering issues.

-            {title} {t(option.nameTranslationKey)}
+            {title} {t(option.nameTranslationKey || "select_date")}

Likely invalid or redundant comment.

web/core/components/issues/issue-layouts/quick-add/root.tsx (4)

10-10: LGTM! Translation hook properly integrated.

The useTranslation hook is correctly imported and initialized.

Also applies to: 70-71


121-122: Verify translation key case sensitivity.

The implementation looks correct, but there might be case sensitivity mismatches between the code and translation files.

Run this script to verify the translation keys:

#!/bin/bash
# Description: Check case sensitivity of translation keys across all language files
for lang in en es fr ja "zh-CN"; do
  echo "Checking $lang translations for case sensitivity..."
  file="packages/i18n/src/locales/$lang/translations.json"
  jq -r '. | with_entries(select(.key|test("^(success|entity_created_successfully)$";"i")))' "$file"
done

133-134: Verify error message translations exist in all locales.

The error handling uses translation keys that were previously reported as missing.

Run this script to verify the error message translations:

#!/bin/bash
# Description: Check if error message translations exist in all locales
for lang in en es fr ja "zh-CN"; do
  echo "Checking $lang translations for error messages..."
  file="packages/i18n/src/locales/$lang/translations.json"
  jq -r '. | with_entries(select(.key|test("^(error|some_error_occurred_please_try_again)$";"i")))' "$file"
done

188-188: Verify button text translations exist in all locales.

The button text uses translation keys that should be verified.

Run this script to verify the button text translations:

✅ Verification successful

Translation keys verified and present in all locales

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if button text translations exist in all locales
for lang in en es fr ja "zh-CN"; do
  echo "Checking $lang translations for button text..."
  file="packages/i18n/src/locales/$lang/translations.json"
  jq -r '. | with_entries(select(.key|test("^(new|epic|issue)$";"i")))' "$file"
done

Length of output: 1821

packages/i18n/src/locales/zh-CN/translations.json (1)

Line range hint 285-408: LGTM! Chinese translations are complete and accurate.

All required translation keys are present with appropriate translations.

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

76-76: LGTM! Japanese translations are complete and accurate.

The translations are properly implemented, including the simplified "custom" translation.

Also applies to: 319-408

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

77-77: LGTM! English translations are complete and accurate.

All translations are properly implemented with correct pluralization rules.

Also applies to: 319-411

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

76-76: LGTM! Spanish translations are complete and accurate.

All translations are properly implemented with correct pluralization rules.

Also applies to: 319-408

packages/i18n/src/locales/fr/translations.json (3)

319-322: LGTM! Core functionality translations are accurate.

The translations for core functionality terms ("inbox", "issue", "layout", "filters") are concise and consistent with French terminology.


354-361: LGTM! Time-related translations are well-structured.

The translations for relative time expressions are consistent and natural in French:

  • Past expressions: "... avant"
  • Future expressions: "... après"

402-404: Review string interpolation syntax.

The translations contain variable interpolation that needs verification:

  1. Line 402: Correct pluralization handling with {{count}}.
  2. Line 403-404: The {entity} placeholder might need to be wrapped in curly braces for consistency.

"project_issues_count": "{{count, plural, =0{Aucun problème} one{# problème} other{# problèmes}}}",
"adding_issue": "Ajout de {entity}...",
"entity_created_successfully": "{entity} créé avec succès",
"entity_title_required": "{entity} title is required.",
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 17, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix untranslated text.

Line 405 contains English text that needs to be translated to French.

-  "entity_title_required": "{entity} title is required.",
+  "entity_title_required": "Le titre de {entity} est requis.",
📝 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
"entity_title_required": "{entity} title is required.",
"entity_title_required": "Le titre de {entity} est requis.",

Copy link
Member

Choose a reason for hiding this comment

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

Update this as well @mathalav55

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

"search_results_for": "Search results for",
"in_project": "In project",
"type_to_search": "Type to search...",
"1_week_ago": "1 week ago",
Copy link
Member

Choose a reason for hiding this comment

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

Can we not group them in a better way? These are part of our date filters.
Let's start organizing them so that it becomes easier to structure everything.

Also, let's keep all the common terms nested under common translations. That way we can access them like common.project and it will be easier to find and replace these terms if we want to group them.

"comment_created_successfully": "Comment created successfully",
"comment_creation_failed_please_try_again_later": "Comment creation failed. Please try again later.",
"missing_fields": "Missing fields",
"comment_updated_successfully": "Comment updated successfully",
Copy link
Member

Choose a reason for hiding this comment

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

This can also be structured as:

"comments": {
  "create": {
    "success": {
      "title": "Comment created",
      description: "Your comment has been created successfully."
    },
    "error": {
      "title": "Comment creation failed",
      description: "Your comment could not be created. Please try again."
    }
  }
}

@@ -84,7 +87,7 @@ const ButtonContent: React.FC<ButtonContentProps> = (props) => {
{value.length > 0
? value.length === 1
? `${getModuleById(value[0])?.name || "module"}`
: `${value.length} Module${value.length === 1 ? "" : "s"}`
: `${value.length} ${value.length === 1 ? t("module") : t("modules")}`
Copy link
Member

Choose a reason for hiding this comment

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

Can we handle it like this:

  "module": "{count, plural, one{Module} other{Modules}}",
  
  //  {t("module", { count: 1 })}
  //  {t("module", { count: 2 })}

Casing can be handle like:

  "module": "{casing, select, capital{{count, plural, one{Module} other{Modules}}} other{{count, plural, one{module} other{modules}}}}",
  // or
    "module.capital": "{count, plural, one{Module} other{Modules}}",
      "module.lower": "{count, plural, one{module} other{modules}}",

{ key: "assignees", title: "Assignees" },
{ key: "created_by", title: "Created By" },
{ key: null, title: "None" },
{ key: "state", title: "States", titleTranslationKey: "states" },
Copy link
Member

Choose a reason for hiding this comment

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

Remove title from all these places if it's no longer being used.

{ key: "estimate", title: "Estimate" },
{ key: "modules", title: "Modules" },
{ key: "cycle", title: "Cycle" },
{ key: "key", title: "ID", titleTranslationKey: "id" },
Copy link
Member

Choose a reason for hiding this comment

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

Here as well, check and remove title if not being used.

[EIssueLayoutTypes.KANBAN]: { key: EIssueLayoutTypes.KANBAN, title: "Board layout", label: "Board", icon: Kanban },
[EIssueLayoutTypes.LIST]: {
key: EIssueLayoutTypes.LIST,
title: "List layout",
Copy link
Member

Choose a reason for hiding this comment

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

Check and remove title.

@@ -1,33 +1,40 @@
export const DATE_AFTER_FILTER_OPTIONS = [
{
name: "1 week from now",
nameTranslationKey: "1_week_from_now",
Copy link
Member

Choose a reason for hiding this comment

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

Check and remove name if we are not using it anywhere.

"project_issues_count": "{{count, plural, =0{Aucun problème} one{# problème} other{# problèmes}}}",
"adding_issue": "Ajout de {entity}...",
"entity_created_successfully": "{entity} créé avec succès",
"entity_title_required": "{entity} title is required.",
Copy link
Member

Choose a reason for hiding this comment

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

Update this as well @mathalav55

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌟enhancement New feature or request 🌐frontend
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants