Skip to content

.gitattributes追加、Vue i18nのheader条件対応、日数ラベル置換、ja.json更新 - #4

Open
shgumo wants to merge 2 commits into
dev/i18nfrom
dev/l10n-ja
Open

.gitattributes追加、Vue i18nのheader条件対応、日数ラベル置換、ja.json更新#4
shgumo wants to merge 2 commits into
dev/i18nfrom
dev/l10n-ja

Conversation

@shgumo

@shgumo shgumo commented Sep 4, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • 新機能
    • 各種リスト/ページ(タスク、アセット、シーケンス、ショット等)の件数表示がヘッダー翻訳に対応。該当キーがあれば「ヘッダー+件数」、なければ従来の「数値+名称」に自動切替。
    • 所要時間表示を再設計。「実績日数」「予定日数」ラベルと共通単位(日)で一貫表示。日本語翻訳を追加・更新。
  • 雑務
    • .gitattributes を追加し、テキストのLF統一・WindowsバッチのCRLF維持・画像/フォント等のバイナリ扱いを明確化。

@shgumo
shgumo requested a review from cumuloworks September 4, 2025 06:17
@coderabbitai

coderabbitai Bot commented Sep 4, 2025

Copy link
Copy Markdown

Walkthrough

  • .gitattributesを追加し、LF/CRLFとバイナリ扱いを定義。
  • 多数のVueコンポーネントで件数表示を「header」キー有無で条件分岐するi18nロジックを導入。
  • 日数ラベル表示(days_spent_label / days_estimated_label)へ置換。
  • ja.jsonにheaderキーや日数ラベルなどを追加・更新。

Changes

Cohort / File(s) Summary
Repo config
./.gitattributes
テキストをLFに正規化(text=auto eol=lf)、*.bat/*.cmdはCRLF、画像/フォント等をbinary指定。
Headerベースの件数表示(lists)
src/components/lists/AssetTypeList.vue, .../BackgroundList.vue, .../CustomActionList.vue, .../DepartmentList.vue, .../HardwareItemList.vue, .../PeopleTimesheetList.vue, .../ProductionAssetTypeList.vue, .../ProductionList.vue, .../ProductionTeamList.vue, .../SequenceStatsList.vue, .../SoftwareLicenseList.vue, .../StudioList.vue, .../TaskStatusList.vue, .../TaskTypeList.vue, .../TimesheetList.vue
$te('...header')の有無で、件数見出し($tc header)か従来の「数値+number」表示に分岐。公開API変更なし。
Header+日数ラベル対応(lists・一部)
src/components/lists/AllTaskList.vue, .../AssetList.vue, .../EditList.vue, .../EpisodeList.vue, .../SequenceList.vue, .../ShotList.vue, .../TodosList.vue
上記のheader分岐に加え、所要/消費日数表示を$t('main.days_*_label')main.days構成へ変更(従来の$tcベースから移行)。
Pages: Assets件数のheader化
src/components/pages/Episode.vue, .../Sequence.vue, .../Shot.vue, .../breakdown/ShotLine.vue
キャスティングやブレイクダウンの資産件数表示をassets.header存在時は$tc(header)に、なければ従来の数値+assets.numberに分岐。
Widgets
src/components/widgets/FileUpload.vue, .../TaskListNumbers.vue
ファイル選択数・タスク数の表示を*.headerの有無で分岐($tc(header, {count})/数値+number)。
Production 統計のラベル化
src/components/pages/production/ProductionStats.vue
時間/見積の$tc分岐(時間/日)を撤廃し、main.days_spent_label/main.days_estimated_labelmain.daysで統一表示。
Locales (JA)
src/locales/ja.json
多数のセクションにheaderを追加(assets等)。default.maindays_spent_label/days_estimated_labelを追加し既存日/時キー文言を更新。my_checks.header/people.header/playlists.tasks_header等を追加。

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant C as Vue Component
  participant I as i18n ($te/$tc/$t)

  U->>C: 画面表示
  C->>I: $te('X.header') 存在確認
  alt header が存在
    C->>I: $tc('X.header', count, {count})
    I-->>C: 見出しテキスト
    C-->>U: 見出しのみ表示
  else header が不存在
    C-->>U: 数値( count )
    C->>I: $tc('X.number', count)
    I-->>C: numberテキスト
    C-->>U: 数値+number表示
  end
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant C as Vue Component
  participant I as i18n

  U->>C: 期間表示
  par 消費日数
    C->>I: $te('main.days_spent_label')?
    alt 存在
      C->>I: $t('main.days_spent_label'), $t('main.days')
    else 非存在
      C->>I: $tc('main.days_spent', n)
    end
  and 見積日数
    C->>I: $te('main.days_estimated_label')?
    alt 存在
      C->>I: $t('main.days_estimated_label'), $t('main.days')
    else 非存在
      C->>I: $tc('main.days_estimated', n)
    end
  end
  C-->>U: ラベル+期間を表示
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

ぴょん、と数える件数は
見出しの耳で聞き分ける
日の札をそっと並べて
予定も実績も、月見団子のように
LFの風にゆれながら
わたしは数える、翻訳の草むらで 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev/l10n-ja

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@coderabbitai coderabbitai Bot changed the title @coderabbitai .gitattributes追加、Vue i18nのheader条件対応、日数ラベル置換、ja.json更新 Sep 4, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/locales/ja.json (1)

1424-1449: edits.header が未定義のため、ヘッダー分岐が常にフォールバックに

src/components/lists/EditList.vue$te('edits.header') を参照していますが、ja.jsonedits.header がありません。統一のため追加を推奨します。

       "number": "エディット | エディット",
+      "header": "エディット: {count} 件",
       "restore_text": "アーカイブから {name} を復元してもよろしいですか?",
🧹 Nitpick comments (30)
.gitattributes (1)

5-6: 追加提案: PowerShellや動画/アーカイブ拡張子の扱いを明確化

  • Windows向けPowerShellスクリプトもCRLF維持対象に。
  • よく扱うバイナリ(動画・アーカイブ)も明示しておくと安全です。

適用例:

 *.cmd text eol=crlf
+*.ps1 text eol=crlf
+*.psm1 text eol=crlf

 *.otf binary
+
+# Common media/archives
+*.mp4 binary
+*.mov binary
+*.webm binary
+*.zip binary
+*.gz binary
+*.7z binary

Also applies to: 8-18

src/components/pages/breakdown/ShotLine.vue (1)

252-259: i18n見出しの描画を関数化して重複計算と空文字ノードを回避

nbAssetsForType(assetType) を複数回呼んでおり、先頭で '' を出力しているためテンプレートが冗長です。1回の計算で文字列を返す関数にまとめるとスッキリします。

-        <div class="flexrow-item mb05">
-          {{ $te('assets.header') ? '' : nbAssetsForType(assetType) }}
-          {{
-            $te('assets.header')
-              ? $tc('assets.header', nbAssetsForType(assetType), {
-                  count: nbAssetsForType(assetType)
-                })
-              : $tc('assets.number', nbAssetsForType(assetType))
-          }}
-        </div>
+        <div class="flexrow-item mb05">
+          {{ assetsHeader(assetType) }}
+        </div>

スクリプト部への追加:

methods: {
  // ...
  assetsHeader(assetType) {
    const count = this.nbAssetsForType(assetType)
    return this.$te('assets.header')
      ? this.$tc('assets.header', count, { count })
      : `${count} ${this.$tc('assets.number', count)}`
  }
}
src/components/lists/EditList.vue (1)

479-486: ヘッダー描画の条件分岐はOKだが、空文字ノードは避けたい

$te('edits.header') ? '' : … は空文字ノードを生成します。<template v-if> で分岐するか、専用関数化で回避してください。

-  {{ $te('edits.header') ? '' : displayedEditsLength }}
-  {{
-    $te('edits.header')
-      ? $tc('edits.header', displayedEditsLength, { count: displayedEditsLength })
-      : $tc('edits.number', displayedEditsLength)
-  }}
+  <template v-if="$te('edits.header')">
+    {{ $tc('edits.header', displayedEditsLength, { count: displayedEditsLength }) }}
+  </template>
+  <template v-else>
+    {{ displayedEditsLength }} {{ $tc('edits.number', displayedEditsLength) }}
+  </template>
src/locales/ja.json (1)

62-71: backgrounds の一部英語表記の和訳整備

UI一貫性のため、英語のまま残っている文言(例: "3D Backgrounds Library", "Edit background", "Add a new background")も和訳をご検討ください。

src/components/lists/TimesheetList.vue (1)

176-181: フォールバックは tasks.number を使う方が他画面と整合しやすい

現在はフォールバックで tasks.tasks$tc に渡していますが、他リストでは *.number を用いており多言語でも無難です。

-      {{
-        $te('tasks.tasks_header')
-          ? $tc('tasks.tasks_header', tasks.length, { count: tasks.length })
-          : $tc('tasks.tasks', tasks.length)
-      }}
+      {{
+        $te('tasks.tasks_header')
+          ? $tc('tasks.tasks_header', tasks.length, { count: tasks.length })
+          : $tc('tasks.number', tasks.length)
+      }}
src/components/pages/Episode.vue (1)

120-125: casting件数の表示も同様に単一分岐+countパラメータで簡潔化できます

  • $te を1回だけにし、fallback側 $tc('assets.number', ...) にも { count } を渡すと一貫性が上がります。
-            {{ $te('assets.header') ? '' : nbAssets }}
-            {{
-              $te('assets.header')
-                ? $tc('assets.header', nbAssets, { count: nbAssets })
-                : $tc('assets.number', nbAssets)
-            }}
+            <template v-if="$te('assets.header')">
+              {{ $tc('assets.header', nbAssets, { count: nbAssets }) }}
+            </template>
+            <template v-else>
+              {{ nbAssets }} {{ $tc('assets.number', nbAssets, { count: nbAssets }) }}
+            </template>
src/components/lists/ProductionTeamList.vue (1)

56-61: people件数の表記を統一($teは1回、$tcにcountを渡す)

  • 他コンポーネントと同じ書き方に寄せ、将来のロケール文言変更にも強くしておきましょう。
-      {{ $te('people.header') ? '' : entries.length }}
-      {{
-        $te('people.header')
-          ? $tc('people.header', entries.length, { count: entries.length })
-          : $tc('people.persons', entries.length)
-      }}
+      <template v-if="$te('people.header')">
+        {{ $tc('people.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('people.persons', entries.length, { count: entries.length }) }}
+      </template>
src/components/lists/SequenceStatsList.vue (1)

132-139: sequences件数のヘッダー分岐を簡潔化+fallbackにcountを渡す

  • $te 二重評価回避と { count } 付与の統一対応です。
-      {{ $te('sequences.header') ? '' : displayedSequencesLength }}
-      {{
-        $te('sequences.header')
-          ? $tc('sequences.header', displayedSequencesLength, {
-              count: displayedSequencesLength
-            })
-          : $tc('sequences.number', displayedSequencesLength)
-      }}
+      <template v-if="$te('sequences.header')">
+        {{ $tc('sequences.header', displayedSequencesLength, { count: displayedSequencesLength }) }}
+      </template>
+      <template v-else>
+        {{ displayedSequencesLength }}
+        {{ $tc('sequences.number', displayedSequencesLength, { count: displayedSequencesLength }) }}
+      </template>
src/components/widgets/TaskListNumbers.vue (1)

3-7: tasks件数の分岐整理($teは1回)とcountパラメータの統一適用

  • 表示ロジックをv-if/v-elseで一本化し、fallback側 $tc('tasks.number', ...) にも { count } を渡してください。
  • なお、PRで days_*_label が追加されているため、別PR/別コミットでラベル運用へ移行する際は本コンポーネントの所要文言も併せて見直すと整合がとれます(任意)。
-    {{ $te('tasks.header') ? '' : tasks.length }}
-    {{
-      $te('tasks.header')
-        ? $tc('tasks.header', tasks.length, { count: tasks.length })
-        : $tc('tasks.number', tasks.length)
-    }}
+    <template v-if="$te('tasks.header')">
+      {{ $tc('tasks.header', tasks.length, { count: tasks.length }) }}
+    </template>
+    <template v-else>
+      {{ tasks.length }} {{ $tc('tasks.number', tasks.length, { count: tasks.length }) }}
+    </template>

Also applies to: 9-9

src/components/lists/ProductionList.vue (1)

142-147: $te の二重評価と空文字出力をやめ、v-if/else で明示分岐にすると読みやすいです

条件を明示し、無駄な評価と不要な空文字の描画を避けられます。

-      {{ $te('productions.header') ? '' : entries.length }}
-      {{
-        $te('productions.header')
-          ? $tc('productions.header', entries.length, { count: entries.length })
-          : $tc('productions.number', entries.length)
-      }}
+      <template v-if="$te('productions.header')">
+        {{ $tc('productions.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('productions.number', entries.length) }}
+      </template>
src/components/lists/DepartmentList.vue (1)

52-57: 同様に、明示的な v-if/else にして可読性と意図を強化しましょう

描画条件がひと目で分かるようになります。

-      {{ $te('departments.header') ? '' : entries.length }}
-      {{
-        $te('departments.header')
-          ? $tc('departments.header', entries.length, { count: entries.length })
-          : $tc('departments.number', entries.length)
-      }}
+      <template v-if="$te('departments.header')">
+        {{ $tc('departments.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('departments.number', entries.length) }}
+      </template>
src/components/lists/TaskStatusList.vue (1)

88-93: ヘッダー有無の分岐はテンプレートで行い、空文字評価を排除

他ファイルと同様のパターンで統一しましょう。

-      {{ $te('task_status.header') ? '' : entries.length }}
-      {{
-        $te('task_status.header')
-          ? $tc('task_status.header', entries.length, { count: entries.length })
-          : $tc('task_status.number', entries.length)
-      }}
+      <template v-if="$te('task_status.header')">
+        {{ $tc('task_status.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('task_status.number', entries.length) }}
+      </template>
src/components/lists/TaskTypeList.vue (1)

75-80: 二重の $te 呼び出しを避けて v-if/else へ

微小ですが毎描画の無駄を減らせ、読みやすくなります。

-      {{ $te('task_types.header') ? '' : entries.length }}
-      {{
-        $te('task_types.header')
-          ? $tc('task_types.header', entries.length, { count: entries.length })
-          : $tc('task_types.number', entries.length)
-      }}
+      <template v-if="$te('task_types.header')">
+        {{ $tc('task_types.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('task_types.number', entries.length) }}
+      </template>
src/components/lists/PeopleTimesheetList.vue (1)

172-177: テンプレートでの条件分岐に変更し、キー名も他と揃えると一貫性が上がります

fallback 側のキーを people.number に寄せると他リストと統一できます(ロケール側の対応が必要な場合あり)。

-      {{ $te('people.header') ? '' : people.length }}
-      {{
-        $te('people.header')
-          ? $tc('people.header', people.length, { count: people.length })
-          : $tc('people.persons', people.length)
-      }}
+      <template v-if="$te('people.header')">
+        {{ $tc('people.header', people.length, { count: people.length }) }}
+      </template>
+      <template v-else>
+        {{ people.length }} {{ $tc('people.number', people.length) }}
+      </template>
src/components/lists/SoftwareLicenseList.vue (1)

69-76: i18nの条件分岐は意図どおり。ただしテンプレ上の空文字は避け、v-if/v-elseで明示分岐を。

描画で空文字を挟むより、可読性と将来の保守性のために分岐をテンプレート側で切り替えるのが望ましいです。

適用例(同範囲の置換差分):

-      {{ $te('software_licenses.header') ? '' : entries.length }}
-      {{
-        $te('software_licenses.header')
-          ? $tc('software_licenses.header', entries.length, {
-              count: entries.length
-            })
-          : $tc('software_licenses.number', entries.length)
-      }}
+      <span v-if="$te('software_licenses.header')">
+        {{ $tc('software_licenses.header', entries.length, { count: entries.length }) }}
+      </span>
+      <span v-else>
+        {{ entries.length }} {{ $tc('software_licenses.number', entries.length) }}
+      </span>
src/components/pages/production/ProductionStats.vue (1)

55-56: 単位は $t で十分。$tc('main.days') は count 未指定で不適切

この場面の「日」は固定の単位表示なので $t('main.days') に統一しましょう。

修正差分:

-          {{ $tc('main.days') }}
+          {{ $t('main.days') }}
src/components/lists/ProductionAssetTypeList.vue (1)

122-129: v-if/v-else で i18n 分岐を明示化

ja.json に asset_types.header は既に存在するため、三項演算子ではなく下記のように v-ifv-else で出力を分割してください。

@@ src/components/lists/ProductionAssetTypeList.vue:122-129
- {{ $te('asset_types.header') ? '' : displayedAssetTypesLength }}
- {{
-   $te('asset_types.header')
-     ? $tc('asset_types.header', displayedAssetTypesLength, { count: displayedAssetTypesLength })
-     : $tc('asset_types.number', displayedAssetTypesLength)
- }}
+ <span v-if="$te('asset_types.header')">
+   {{ $tc('asset_types.header', displayedAssetTypesLength, { count: displayedAssetTypesLength }) }}
+ </span>
+ <span v-else>
+   {{ displayedAssetTypesLength }} {{ $tc('asset_types.number', displayedAssetTypesLength) }}
+ </span>

同様の分岐が他のリストにも散見されるため、
<CountHeader key-path="asset_types" :count="displayedAssetTypesLength" /> のような小さな共通コンポーネント化もご検討ください。

src/components/lists/HardwareItemList.vue (1)

57-64: i18n分岐は妥当。空文字を避けて v-if/v-else で整理を

可読性のため、空文字ではなくテンプレート分岐で出し分けましょう。

置換差分:

-      {{ $te('hardware_items.header') ? '' : entries.length }}
-      {{
-        $te('hardware_items.header')
-          ? $tc('hardware_items.header', entries.length, {
-              count: entries.length
-            })
-          : $tc('hardware_items.number', entries.length)
-      }}
+      <span v-if="$te('hardware_items.header')">
+        {{ $tc('hardware_items.header', entries.length, { count: entries.length }) }}
+      </span>
+      <span v-else>
+        {{ entries.length }} {{ $tc('hardware_items.number', entries.length) }}
+      </span>
src/components/lists/StudioList.vue (1)

34-39: i18nヘッダーのフォールバックは妥当。空文字と二重評価を避けて1式に集約を

現在は $te を2回評価し、ヘッダー有りの場合に空文字も描画しています。不要な空白と二重評価を避け、1つの補間式にまとめるとシンプルです。

-      {{ $te('studios.header') ? '' : entries.length }}
-      {{
-        $te('studios.header')
-          ? $tc('studios.header', entries.length, { count: entries.length })
-          : $tc('studios.number', entries.length)
-      }}
+      {{ $te('studios.header')
+          ? $tc('studios.header', entries.length, { count: entries.length })
+          : `${entries.length} ${$tc('studios.number', entries.length)}` }}
src/components/lists/BackgroundList.vue (1)

49-54: OKだが、同様に1式へ集約して余分な空白と二重評価を排除しましょう

$te の二重評価と空文字出力をやめ、1つの式にまとめると読みやすくなります。

-      {{ $te('backgrounds.header') ? '' : entries.length }}
-      {{
-        $te('backgrounds.header')
-          ? $tc('backgrounds.header', entries.length, { count: entries.length })
-          : $tc('backgrounds.number', entries.length)
-      }}
+      {{ $te('backgrounds.header')
+          ? $tc('backgrounds.header', entries.length, { count: entries.length })
+          : `${entries.length} ${$tc('backgrounds.number', entries.length)}` }}
src/components/pages/Shot.vue (1)

51-56: 式の集約で冗長さを解消し、不要な空白を回避

Sequence.vue と同様、1つの補間式にまとめると読みやすく保守もしやすくなります。必要であれば 0 件時の非表示も検討ください(Sequence.vue との整合)。

-            {{ $te('assets.header') ? '' : nbAssets }}
-            {{
-              $te('assets.header')
-                ? $tc('assets.header', nbAssets, { count: nbAssets })
-                : $tc('assets.number', nbAssets)
-            }}
+            {{ $te('assets.header')
+                ? $tc('assets.header', nbAssets, { count: nbAssets })
+                : `${nbAssets} ${$tc('assets.number', nbAssets)}` }}
src/components/lists/CustomActionList.vue (1)

48-55: 良い対応。1式にまとめて余分な空白と二重評価を削減

他リストと同様に、1つの式へ集約することでパターンを統一できます。

-      {{ $te('custom_actions.header') ? '' : entries.length }}
-      {{
-        $te('custom_actions.header')
-          ? $tc('custom_actions.header', entries.length, {
-              count: entries.length
-            })
-          : $tc('custom_actions.number', entries.length)
-      }}
+      {{ $te('custom_actions.header')
+          ? $tc('custom_actions.header', entries.length, { count: entries.length })
+          : `${entries.length} ${$tc('custom_actions.number', entries.length)}` }}
src/components/pages/MyChecks.vue (1)

64-71: $te の二重評価と空文字ノードを避け、読みやすさを向上させましょう

テンプレート内で $te('my_checks.header') を2回呼び出しており、さらに最初のマスタッシュで空文字を出力しています。v-if / v-else に置き換えると評価も1回になり、意図が明確になります。

-            {{ $te('my_checks.header') ? '' : nbTasksToCheck }}
-            {{
-              $te('my_checks.header')
-                ? $tc('my_checks.header', nbTasksToCheck, {
-                    count: nbTasksToCheck
-                  })
-                : $tc('my_checks.title', nbTasksToCheck)
-            }}
+            <template v-if="$te('my_checks.header')">
+              {{ $tc('my_checks.header', nbTasksToCheck, { count: nbTasksToCheck }) }}
+            </template>
+            <template v-else>
+              {{ nbTasksToCheck }} {{ $tc('my_checks.title', nbTasksToCheck) }}
+            </template>
src/components/lists/AssetList.vue (1)

555-562: ヘッダー表示ロジックを1つの式に集約し、重複評価を削減

$te('assets.header') を2回評価し、2つのテキストノードに分割して描画しています。1つの式に統合すると読みやすさと保守性が上がります(他リストと同様の共通パターン化もしやすくなります)。

-      {{ $te('assets.header') ? '' : displayedAssetsLength }}
-      {{
-        $te('assets.header')
-          ? $tc('assets.header', displayedAssetsLength, {
-              count: displayedAssetsLength
-            })
-          : $tc('assets.number', displayedAssetsLength)
-      }}
+      {{
+        $te('assets.header')
+          ? $tc('assets.header', displayedAssetsLength, { count: displayedAssetsLength })
+          : `${displayedAssetsLength} ${$tc('assets.number', displayedAssetsLength)}`
+      }}
src/components/lists/ShotList.vue (2)

775-782: ヘッダー描画の簡素化(1式化)

$te('shots.header') の重複評価と二段描画を解消し、可読性を上げましょう。

-      {{ $te('shots.header') ? '' : displayedShotsLength }}
-      {{
-        $te('shots.header')
-          ? $tc('shots.header', displayedShotsLength, {
-              count: displayedShotsLength
-            })
-          : $tc('shots.number', displayedShotsLength)
-      }}
+      {{
+        $te('shots.header')
+          ? $tc('shots.header', displayedShotsLength, { count: displayedShotsLength })
+          : `${displayedShotsLength} ${$tc('shots.number', displayedShotsLength)}`
+      }}

796-807: 単位の複数形対応($t → $tc)+各ファイルでの統一

$t('main.days') は複数形を考慮しません。$tc('main.days', count) を使うと他言語対応が堅牢になります(日本語では影響小ですが、共通化の観点で推奨)。なお、AssetList.vue / SequenceList.vue も同じ方針へ寄せると一貫性が保てます。

  • 変更前提: 各ロケールに main.days の複数形定義があること。
-            ? `${$t('main.days_spent_label')} ${formatDuration(displayedShotsTimeSpent)} ${$t('main.days')}`
+            ? `${$t('main.days_spent_label')} ${formatDuration(displayedShotsTimeSpent)} ${$tc('main.days', displayedShotsTimeSpent)}`
-            : `${formatDuration(displayedShotsTimeSpent)} ${$tc('main.days_spent', displayedShotsTimeSpent)}`
+            : `${formatDuration(displayedShotsTimeSpent)} ${$tc('main.days_spent', displayedShotsTimeSpent)}`
-            ? `${$t('main.days_estimated_label')} ${formatDuration(displayedShotsEstimation)} ${$t('main.days')}`
+            ? `${$t('main.days_estimated_label')} ${formatDuration(displayedShotsEstimation)} ${$tc('main.days', displayedShotsEstimation)}`
-            : `${formatDuration(displayedShotsEstimation)} ${$tc('main.days_estimated', displayedShotsEstimation)}`
+            : `${formatDuration(displayedShotsEstimation)} ${$tc('main.days_estimated', displayedShotsEstimation)}`
src/components/lists/SequenceList.vue (2)

461-468: ヘッダー表示の1式化(重複 $te の排除)

他コンポーネントと同様に、1つの式へ統合してください。

-      {{ $te('sequences.header') ? '' : displayedSequencesLength }}
-      {{
-        $te('sequences.header')
-          ? $tc('sequences.header', displayedSequencesLength, {
-              count: displayedSequencesLength
-            })
-          : $tc('sequences.number', displayedSequencesLength)
-      }}
+      {{
+        $te('sequences.header')
+          ? $tc('sequences.header', displayedSequencesLength, { count: displayedSequencesLength })
+          : `${displayedSequencesLength} ${$tc('sequences.number', displayedSequencesLength)}`
+      }}

474-480: 単位の二重表示リスクと他ファイルとの仕様差の是正

  • 現状は formatDuration(...) + ' ' + $t('main.days') 固定ですが、formatDuration が単位付与する実装だと二重化します。ShotList.vue と同様のフォールバック方式へ寄せると安全です。

  • なお、この <span> 自体の表示条件は(変更外ですが)displayedSequencesTimeSpent > 0 && displayedSequencesEstimation > 0 で、Asset/Shot の「どちらか > 0」で表示する実装と不一致です。仕様かどうか確認をお願いします。

  • 仕様確認: 時間と見積りの少なくとも一方が0より大きければ表示すべきか(Asset/Shot と統一するか)。

  • 実装確認: formatDuration の返り値に単位が含まれるか。

-        (
-        {{ $t('main.days_spent_label') }}
-        {{ formatDuration(displayedSequencesTimeSpent) }} {{ $t('main.days') }},
-        {{ $t('main.days_estimated_label') }}
-        {{ formatDuration(displayedSequencesEstimation) }}
-        {{ $t('main.days') }})
+        (
+        {{
+          $te('main.days_spent_label')
+            ? `${$t('main.days_spent_label')} ${formatDuration(displayedSequencesTimeSpent)} ${$t('main.days')}`
+            : `${formatDuration(displayedSequencesTimeSpent)} ${$tc('main.days_spent', displayedSequencesTimeSpent)}`
+        }},
+        {{
+          $te('main.days_estimated_label')
+            ? `${$t('main.days_estimated_label')} ${formatDuration(displayedSequencesEstimation)} ${$t('main.days')}`
+            : `${formatDuration(displayedSequencesEstimation)} ${$tc('main.days_estimated', displayedSequencesEstimation)}`
+        }})
src/components/lists/EpisodeList.vue (2)

507-511: 日数の単位と句読点をローカライズ可能に

main.days を固定文言で出しているため、英語など単複形が必要なロケールで「1 days」となる恐れがあります。main.days_unit(複数形対応キー)があれば $tc で使い、無ければ従来の main.days にフォールバックする実装が安全です。併せて、将来的には括弧・区切りも含めて1キーにまとめると(全言語で)句読点までローカライズ可能になります。

-        (
-        {{ $t('main.days_spent_label') }}
-        {{ formatDuration(displayedEpisodesTimeSpent) }} {{ $t('main.days') }},
-        {{ $t('main.days_estimated_label') }}
-        {{ formatDuration(displayedEpisodesEstimation) }} {{ $t('main.days') }})
+        (
+        {{ $t('main.days_spent_label') }}
+        {{ formatDuration(displayedEpisodesTimeSpent) }}
+        {{
+          $te('main.days_unit')
+            ? $tc('main.days_unit', displayedEpisodesTimeSpent)
+            : $t('main.days')
+        }},
+        {{ $t('main.days_estimated_label') }}
+        {{ formatDuration(displayedEpisodesEstimation) }}
+        {{
+          $te('main.days_unit')
+            ? $tc('main.days_unit', displayedEpisodesEstimation)
+            : $t('main.days')
+        }})

補足: ロケール側に main.days_unit(例: "day | days")が無ければ追加をご検討ください。句読点まで含める場合は、episodes.time_summary のような1キー(プレースホルダ: {spent_label}, {spent}, {spent_unit}, {estimated_label}, {estimated}, {estimated_unit})化が有効です。


496-503: 任意: $tc('episodes.number') にも count パラメータを渡す
検証の結果、現状のすべての episodes.number{count} は含まれておらず二重表示のリスクはありませんでした。将来のロケール追加時の安全性担保のため、以下のオプションリファクタを検討してください。

- : $tc('episodes.number', displayedEpisodesLength)
+ : $tc('episodes.number', displayedEpisodesLength, { count: displayedEpisodesLength })
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e02706c and 8333b0d.

📒 Files selected for processing (32)
  • .gitattributes (1 hunks)
  • src/components/lists/AllTaskList.vue (1 hunks)
  • src/components/lists/AssetList.vue (1 hunks)
  • src/components/lists/AssetTypeList.vue (1 hunks)
  • src/components/lists/BackgroundList.vue (1 hunks)
  • src/components/lists/CustomActionList.vue (1 hunks)
  • src/components/lists/DepartmentList.vue (1 hunks)
  • src/components/lists/EditList.vue (1 hunks)
  • src/components/lists/EpisodeList.vue (1 hunks)
  • src/components/lists/HardwareItemList.vue (1 hunks)
  • src/components/lists/PeopleTimesheetList.vue (1 hunks)
  • src/components/lists/ProductionAssetTypeList.vue (1 hunks)
  • src/components/lists/ProductionList.vue (1 hunks)
  • src/components/lists/ProductionTeamList.vue (1 hunks)
  • src/components/lists/SequenceList.vue (1 hunks)
  • src/components/lists/SequenceStatsList.vue (1 hunks)
  • src/components/lists/ShotList.vue (2 hunks)
  • src/components/lists/SoftwareLicenseList.vue (1 hunks)
  • src/components/lists/StudioList.vue (1 hunks)
  • src/components/lists/TaskStatusList.vue (1 hunks)
  • src/components/lists/TaskTypeList.vue (1 hunks)
  • src/components/lists/TimesheetList.vue (1 hunks)
  • src/components/lists/TodosList.vue (1 hunks)
  • src/components/pages/Episode.vue (1 hunks)
  • src/components/pages/MyChecks.vue (1 hunks)
  • src/components/pages/Sequence.vue (1 hunks)
  • src/components/pages/Shot.vue (1 hunks)
  • src/components/pages/breakdown/ShotLine.vue (1 hunks)
  • src/components/pages/production/ProductionStats.vue (1 hunks)
  • src/components/widgets/FileUpload.vue (1 hunks)
  • src/components/widgets/TaskListNumbers.vue (1 hunks)
  • src/locales/ja.json (25 hunks)
🔇 Additional comments (10)
.gitattributes (2)

1-18: 方針は適切(LF統一+WindowsバッチのみCRLF)

全体の設定は妥当です。text=auto eol=lf によりテキストはLFへ統一、.bat/.cmdはCRLF維持、一般的なバイナリも明示されています。


20-20: 末尾に不要な文字列が混入していないか確認してください

最後の行に「20」という単独行があるように見えます。ファイル末尾の不要文字であれば削除してください。

src/locales/ja.json (3)

644-649: 日数・時間ラベルの追加は適切

days_spent_label / days_estimated_label の導入はUIの可読性が上がります。


1705-1731: tasks.tasks_header の追加はTimesheetフッターの新ロジックと整合

TimesheetList.vue$te('tasks.tasks_header') に対応しており、OKです。


1831-1835: キーの綴り(timespents)は既存仕様に依存しているはずなので、このままでOKか要確認

呼び出し側がこのキー名に依存している前提であれば変更不要ですが、将来の整備時に export_time_spent(s) / time_spent(s) へ正規化する計画があれば、段階的移行(両キー併存→呼び出し側置換→旧キー削除)をご検討ください。

src/components/lists/AssetTypeList.vue (1)

54-59: $teの重複評価を1回にまとめ、fallbackにもcountパラメータを追加
以下を適用してください:

  • v-if/v-elseで $te('asset_types.header') を一度だけ呼び出す
  • fallback 側の $tc('asset_types.number') にも { count: entries.length } を渡す
  • ja.json に asset_types.header キーが定義されているか確認する
-      {{ $te('asset_types.header') ? '' : entries.length }}
-      {{
-        $te('asset_types.header')
-          ? $tc('asset_types.header', entries.length, { count: entries.length })
-          : $tc('asset_types.number', entries.length)
-      }}
+      <template v-if="$te('asset_types.header')">
+        {{ $tc('asset_types.header', entries.length, { count: entries.length }) }}
+      </template>
+      <template v-else>
+        {{ entries.length }} {{ $tc('asset_types.number', entries.length, { count: entries.length }) }}
+      </template>

※ 同様パターンが複数ある場合は <CountHeader i18n-key="asset_types" :count="entries.length" /> のような小コンポーネント化を検討してください。

src/components/lists/ProductionList.vue (1)

142-147: i18nキーの存在と{count}プレースホルダー整合を確認

  • 各ロケールのproductions.headerproductions.numberキーが実際に存在し、header値内に{count}が含まれていることを確認してください
  • スクリプトがロケールファイルの配置・命名と合っていないようなので、パスやJSON構造を実際のディレクトリ構成に合わせて修正し、再度チェックを行ってください
src/components/pages/Sequence.vue (1)

127-132: 表示ロジックの条件統一確認と式の集約提案

  • Sequence.vue は v-show="currentSection === 'casting' && nbAssets > 0"、Shot.vue は v-show="currentSection === 'casting'" なので、nbAssets が 0 の場合に表示不整合があります。意図どおりか確認し、必要なら条件を統一してください。
  • $te の二重評価を避け、式を下記のように簡潔に集約できます:
- {{ $te('assets.header') ? '' : nbAssets }}
- {{
-   $te('assets.header')
-     ? $tc('assets.header', nbAssets, { count: nbAssets })
-     : $tc('assets.number', nbAssets)
- }}
+ {{ $te('assets.header')
+     ? $tc('assets.header', nbAssets, { count: nbAssets })
+     : `${nbAssets} ${$tc('assets.number', nbAssets)}` }}
src/components/lists/TodosList.vue (1)

293-298: tasks.header の参照は他に存在しません このファイル以外で tasks.header が使われている箇所は見つかりませんでした。元コメントの前提が誤りのため、この提案は不要です。

Likely an incorrect or invalid review comment.

src/components/lists/AssetList.vue (1)

566-571: formatDuration の単位重複と翻訳キーの検証

  • formatDuration(displayed…) が単位込み文字列を返すか数値のみを返すか実装から確認し、もし単位込みなら後置の {{ $t('main.days') }} を削除してください。
  • 全ロケール(src/locales/*.json)に main.days_spent_labelmain.days_estimated_labelmain.days が定義されているかを確認し、不足があれば ShotList.vue と同様のフォールバック実装に統一してください。
src/components/lists/AssetList.vue (566-571)
-        (
-        {{ $t('main.days_spent_label') }}
-        {{ formatDuration(displayedAssetsTimeSpent) }} {{ $t('main.days') }},
-        {{ $t('main.days_estimated_label') }}
-        {{ formatDuration(displayedAssetsEstimation) }} {{ $t('main.days') }})
+        (
+        {{
+          $te('main.days_spent_label')
+            ? `${$t('main.days_spent_label')} ${formatDuration(displayedAssetsTimeSpent)} ${$t('main.days')}`
+            : `${formatDuration(displayedAssetsTimeSpent)} ${$tc('main.days_spent', displayedAssetsTimeSpent)}`
+        }},
+        {{
+          $te('main.days_estimated_label')
+            ? `${$t('main.days_estimated_label')} ${formatDuration(displayedAssetsEstimation)} ${$t('main.days')}`
+            : `${formatDuration(displayedAssetsEstimation)} ${$tc('main.days_estimated', displayedAssetsEstimation)}`
+        }})

Comment on lines +148 to 165
{{ $te('tasks.header') ? '' : stats.total }}
{{
$te('tasks.header')
? $tc('tasks.header', stats.total, { count: stats.total })
: $tc('tasks.number', stats.total)
}}
{{ $tc('main.days_estimated', isTimeEstimatedPlural) }},
{{ formatDuration(stats.total_duration) }}
{{ $tc('main.days_spent', isTimeSpentPlural) }})
({{ formatDuration(stats.total_estimation) }}
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${$t('main.days')}`
: $tc('main.days_estimated', isTimeEstimatedPlural)
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(stats.total_duration)} ${$t('main.days')}`
: `${formatDuration(stats.total_duration)} ${$tc('main.days_spent', isTimeSpentPlural)}`
}})
</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

合計日数の表記を「estimated/spent」で非対称にしない+$tc の choice を数値へ

  • estimated 側は数値をマスタッシュ外に、spent 側は内に含めており、表記位置が非対称です。両方とも式内で完結させると揃います。
  • $tc の第2引数に boolean(isTimeEstimatedPlural / isTimeSpentPlural)を渡していますが、数値に変更してください。
-      ({{ formatDuration(stats.total_estimation) }}
-      {{
-        $te('main.days_estimated_label')
-          ? `${$t('main.days_estimated_label')} ${$t('main.days')}`
-          : $tc('main.days_estimated', isTimeEstimatedPlural)
-      }},
+      (
+      {{
+        $te('main.days_estimated_label')
+          ? `${$t('main.days_estimated_label')} ${formatDuration(stats.total_estimation)} ${$t('main.days')}`
+          : `${formatDuration(stats.total_estimation)} ${$tc('main.days_estimated', Math.floor(((stats.total_estimation || 0) / 60) / 8))}`
+      }},
       {{
         $te('main.days_spent_label')
           ? `${$t('main.days_spent_label')} ${formatDuration(stats.total_duration)} ${$t('main.days')}`
-          : `${formatDuration(stats.total_duration)} ${$tc('main.days_spent', isTimeSpentPlural)}`
+          : `${formatDuration(stats.total_duration)} ${$tc('main.days_spent', Math.floor(((stats.total_duration || 0) / 60) / 8))}`
       }})
📝 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
{{ $te('tasks.header') ? '' : stats.total }}
{{
$te('tasks.header')
? $tc('tasks.header', stats.total, { count: stats.total })
: $tc('tasks.number', stats.total)
}}
{{ $tc('main.days_estimated', isTimeEstimatedPlural) }},
{{ formatDuration(stats.total_duration) }}
{{ $tc('main.days_spent', isTimeSpentPlural) }})
({{ formatDuration(stats.total_estimation) }}
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${$t('main.days')}`
: $tc('main.days_estimated', isTimeEstimatedPlural)
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(stats.total_duration)} ${$t('main.days')}`
: `${formatDuration(stats.total_duration)} ${$tc('main.days_spent', isTimeSpentPlural)}`
}})
</p>
{{ $te('tasks.header') ? '' : stats.total }}
{{
$te('tasks.header')
? $tc('tasks.header', stats.total, { count: stats.total })
: $tc('tasks.number', stats.total)
}}
(
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${formatDuration(stats.total_estimation)} ${$t('main.days')}`
: `${formatDuration(stats.total_estimation)} ${$tc('main.days_estimated', Math.floor(((stats.total_estimation || 0) / 60) / 8))}`
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(stats.total_duration)} ${$t('main.days')}`
: `${formatDuration(stats.total_duration)} ${$tc('main.days_spent', Math.floor(((stats.total_duration || 0) / 60) / 8))}`
}})
</p>
🤖 Prompt for AI Agents
In src/components/lists/AllTaskList.vue around lines 148 to 165, the estimated
vs spent day labels are rendered asymmetrically and $tc is being called with
booleans; move the formatDuration(stats.total_estimation) expression inside the
estimated label template so both estimated and spent labels are constructed in
the same way, and change the $tc second argument from isTimeEstimatedPlural /
isTimeSpentPlural to the numeric counts (e.g. stats.total_estimation and
stats.total_duration or their day equivalents) so $tc receives a number for
pluralization.

Comment on lines +148 to 153
{{ $te('tasks.header') ? '' : stats.total }}
{{
$te('tasks.header')
? $tc('tasks.header', stats.total, { count: stats.total })
: $tc('tasks.number', stats.total)
}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

ヘッダーキー名の統一方針を確認(tasks.header vs tasks.tasks_header)

同PR内で tasks.header(本ファイル)と tasks.tasks_header(他ファイル)が混在しています。ロケール定義に合わせてどちらかに統一しましょう。影響範囲は一覧で確認できます。


🏁 Script executed:

#!/bin/bash
# 呼び出し側キーの混在を確認
rg -nP "\$te\('tasks(\.tasks_header|\.header)'\)" -C1 --type=vue

# ロケール側での存在確認
fd -a "src/locales" | xargs -I{} rg -nP '"(tasks_header|header)"\s*:' {}

Length of output: 526


以下のスクリプトで .vue コンポーネントと src/locales 配下を再検索し、tasks.headertasks.tasks_header の呼び出し・定義状況を確認してください:


🏁 Script executed:

#!/bin/bash
# コンポーネント内の $te 呼び出しを検索
rg -nP "\$te\('tasks\.(tasks_header|header)'\)" -C1 -g '*.vue'

# ロケール定義ファイル一覧を取得し、キー名を検索
fd . src/locales | grep -E '\.(js|ts|json)$' | xargs -I{} rg -nP "(tasks_header|header)\s*:" -n {}

Length of output: 174


以下のスクリプトで改めて tasks.headertasks.tasks_header の呼び出し・定義を確認してください:


🏁 Script executed:

#!/bin/bash
# Vue コンポーネント内での呼び出しを検索
rg -n "\$te('tasks.header')" -g '*.vue'
rg -n "\$te('tasks.tasks_header')" -g '*.vue'
rg -n "tasks.header" -g '*.vue'
rg -n "tasks.tasks_header" -g '*.vue'

# ロケール定義でのキー名を検索
rg -n '"tasks\.header"\s*:' -g 'src/locales/**/*.{json,js,ts}'
rg -n '"tasks_header"\s*:'    -g 'src/locales/**/*.{json,js,ts}'

Length of output: 2082


tasks.header を tasks.tasks_header に統一してください

AllTaskList.vue と TaskListNumbers.vue で tasks.header を参照していますが、ロケール定義(src/locales/ja.json)には tasks.tasks_header が存在します。他のコンポーネント(TodosList.vue、TimesheetList.vue)も tasks.tasks_header を使っているため、以下の呼び出しをすべて tasks.tasks_header に置換してください。

  • src/components/lists/AllTaskList.vue:
    • $te('tasks.header')$te('tasks.tasks_header')
    • $tc('tasks.header', …)$tc('tasks.tasks_header', …)
  • src/components/widgets/TaskListNumbers.vue: 同様に3行目〜6行目の tasks.headertasks.tasks_header に統一
🤖 Prompt for AI Agents
In src/components/lists/AllTaskList.vue around lines 148-153 and
src/components/widgets/TaskListNumbers.vue around lines 3-6, replace all
occurrences of the obsolete key 'tasks.header' with the correct locale key
'tasks.tasks_header' (i.e. change $te('tasks.header') →
$te('tasks.tasks_header') and $tc('tasks.header', …) → $tc('tasks.tasks_header',
…)) so both components use the same locale key defined in src/locales/ja.json.

Comment on lines +488 to 493
(
{{ $t('main.days_spent_label') }}
{{ formatDuration(displayedEditsTimeSpent) }} {{ $t('main.days') }},
{{ $t('main.days_estimated_label') }}
{{ formatDuration(displayedEditsEstimation) }} {{ $t('main.days') }})
</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

単位の固定化により「時間表示モード」で誤表示になる可能性

設定「format_duration_in_hours」が有効な場合でも、単位を常に「日」で表示しています。単位は設定に追従させてください。

-        (
-        {{ $t('main.days_spent_label') }}
-        {{ formatDuration(displayedEditsTimeSpent) }} {{ $t('main.days') }},
-        {{ $t('main.days_estimated_label') }}
-        {{ formatDuration(displayedEditsEstimation) }} {{ $t('main.days') }})
+        (
+        {{ $t('main.days_spent_label') }}
+        {{ formatDuration(displayedEditsTimeSpent) }} {{ $t(durationUnitKey) }},
+        {{ $t('main.days_estimated_label') }}
+        {{ formatDuration(displayedEditsEstimation) }} {{ $t(durationUnitKey) }})

補足(スクリプト部の追加例):

computed: {
  // 既存mapGettersに organisation を追加するか、他の設定参照元を使用
  durationUnitKey() {
    return this.organisation?.format_duration_in_hours ? 'main.hour' : 'main.day'
  }
}
  • 既に分単位等へ変換する別ロジックがある場合は、その単位キーを流用してください。

Comment on lines +293 to +309
{{ $te('tasks.tasks_header') ? '' : tasks.length }}
{{
$te('tasks.tasks_header')
? $tc('tasks.tasks_header', tasks.length, { count: tasks.length })
: $tc('tasks.tasks', tasks.length)
}}
{{ $tc('main.days_estimated', isTimeEstimatedPlural) }},
{{ formatDuration(timeSpent) }}
{{ $tc('main.days_spent', isTimeSpentPlural) }})
(
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${formatDuration(timeEstimated)} ${$t('main.days')}`
: `${formatDuration(timeEstimated)} ${$tc('main.days_estimated', isTimeEstimatedPlural)}`
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(timeSpent)} ${$t('main.days')}`
: `${formatDuration(timeSpent)} ${$tc('main.days_spent', isTimeSpentPlural)}`
}})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

$tc の choice に boolean を渡さないでください(数値に変更)

$tc の第2引数は複数形選択のための数値です。現在は isTimeEstimatedPlural / isTimeSpentPlural の boolean を渡しており、英語などの多言語で誤ったフォームが選ばれる可能性があります。分単位から日数(整数)に換算した値を渡してください。

-      {{
-        $te('main.days_estimated_label')
-          ? `${$t('main.days_estimated_label')} ${formatDuration(timeEstimated)} ${$t('main.days')}`
-          : `${formatDuration(timeEstimated)} ${$tc('main.days_estimated', isTimeEstimatedPlural)}`
-      }},
+      {{
+        $te('main.days_estimated_label')
+          ? `${$t('main.days_estimated_label')} ${formatDuration(timeEstimated)} ${$t('main.days')}`
+          : `${formatDuration(timeEstimated)} ${$tc('main.days_estimated', Math.floor(((timeEstimated || 0) / 60) / 8))}`
+      }},
       {{
         $te('main.days_spent_label')
           ? `${$t('main.days_spent_label')} ${formatDuration(timeSpent)} ${$t('main.days')}`
-          : `${formatDuration(timeSpent)} ${$tc('main.days_spent', isTimeSpentPlural)}`
+          : `${formatDuration(timeSpent)} ${$tc('main.days_spent', Math.floor(((timeSpent || 0) / 60) / 8))}`
       }}
📝 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
{{ $te('tasks.tasks_header') ? '' : tasks.length }}
{{
$te('tasks.tasks_header')
? $tc('tasks.tasks_header', tasks.length, { count: tasks.length })
: $tc('tasks.tasks', tasks.length)
}}
{{ $tc('main.days_estimated', isTimeEstimatedPlural) }},
{{ formatDuration(timeSpent) }}
{{ $tc('main.days_spent', isTimeSpentPlural) }})
(
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${formatDuration(timeEstimated)} ${$t('main.days')}`
: `${formatDuration(timeEstimated)} ${$tc('main.days_estimated', isTimeEstimatedPlural)}`
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(timeSpent)} ${$t('main.days')}`
: `${formatDuration(timeSpent)} ${$tc('main.days_spent', isTimeSpentPlural)}`
}})
{{ $te('tasks.tasks_header') ? '' : tasks.length }}
{{
$te('tasks.tasks_header')
? $tc('tasks.tasks_header', tasks.length, { count: tasks.length })
: $tc('tasks.tasks', tasks.length)
}}
(
{{
$te('main.days_estimated_label')
? `${$t('main.days_estimated_label')} ${formatDuration(timeEstimated)} ${$t('main.days')}`
: `${formatDuration(timeEstimated)} ${$tc('main.days_estimated', Math.floor(((timeEstimated || 0) / 60) / 8))}`
}},
{{
$te('main.days_spent_label')
? `${$t('main.days_spent_label')} ${formatDuration(timeSpent)} ${$t('main.days')}`
: `${formatDuration(timeSpent)} ${$tc('main.days_spent', Math.floor(((timeSpent || 0) / 60) / 8))}`
}})

Comment on lines 10 to 19
{{ formatDuration(stats.total_duration) }}
{{
isDurationInHours
? $tc('main.hours_spent', formatDuration(stats.total_duration))
: $tc('main.days_spent', formatDuration(stats.total_duration))
}}
{{ $t('main.days_spent_label') }}
{{ formatDuration(stats.total_duration) }}
{{ $t('main.days') }}
/
{{ formatDuration(stats.total_estimation) }}
{{
isDurationInHours
? $tc(
'main.hours_estimated',
formatDuration(stats.total_estimation)
)
: $tc('main.days_estimated', formatDuration(stats.total_estimation))
}}
{{ $t('main.days_estimated_label') }}
{{ formatDuration(stats.total_estimation) }}
{{ $t('main.days') }}
</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

日数の数値が二重表示されるバグ

formatDuration(...) が「ラベル導入前の出力」と「ラベル導入後の出力」で重複しています。片方を削除し、ラベル→数値→単位の順で統一してください。

修正差分:

-        {{ formatDuration(stats.total_duration) }}
-        {{ $t('main.days_spent_label') }}
-        {{ formatDuration(stats.total_duration) }}
-        {{ $t('main.days') }}
-        /
-        {{ formatDuration(stats.total_estimation) }}
-        {{ $t('main.days_estimated_label') }}
-        {{ formatDuration(stats.total_estimation) }}
-        {{ $t('main.days') }}
+        {{ $t('main.days_spent_label') }} {{ formatDuration(stats.total_duration) }} {{ $t('main.days') }}
+        /
+        {{ $t('main.days_estimated_label') }} {{ formatDuration(stats.total_estimation) }} {{ $t('main.days') }}
📝 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
{{ formatDuration(stats.total_duration) }}
{{
isDurationInHours
? $tc('main.hours_spent', formatDuration(stats.total_duration))
: $tc('main.days_spent', formatDuration(stats.total_duration))
}}
{{ $t('main.days_spent_label') }}
{{ formatDuration(stats.total_duration) }}
{{ $t('main.days') }}
/
{{ formatDuration(stats.total_estimation) }}
{{
isDurationInHours
? $tc(
'main.hours_estimated',
formatDuration(stats.total_estimation)
)
: $tc('main.days_estimated', formatDuration(stats.total_estimation))
}}
{{ $t('main.days_estimated_label') }}
{{ formatDuration(stats.total_estimation) }}
{{ $t('main.days') }}
</span>
{{ $t('main.days_spent_label') }} {{ formatDuration(stats.total_duration) }} {{ $t('main.days') }}
/
{{ $t('main.days_estimated_label') }} {{ formatDuration(stats.total_estimation) }} {{ $t('main.days') }}
🤖 Prompt for AI Agents
In src/components/pages/production/ProductionStats.vue around lines 10 to 19,
the duration values are rendered twice because formatDuration(...) is output
both before and after the label; remove the duplicated occurrences so each block
follows the order: label, numeric value (formatDuration(...)), unit
($t('main.days') or $t('main.days_estimated_label') as appropriate). Ensure you
leave exactly one formatDuration(...) per metric and arrange each segment as: {{
$t('..._label') }} {{ formatDuration(...) }} {{ $t('main.days') }} (or the
estimated label variant).

Comment on lines +33 to +40
{{ $te('main.files_selected_header') ? '' : uploadedFiles.length }}
{{
$te('main.files_selected_header')
? $tc('main.files_selected_header', uploadedFiles.length, {
count: uploadedFiles.length
})
: $tc('main.files_selected')
}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

$tc に count 未指定。複数形選択やロケール別分岐が崩れる可能性あり。

fallback 側の $tc('main.files_selected') に選択数が渡っていません。複数ファイル時のみ表示されるブロックなので、確実に count を渡してください。

修正差分:

-              : $tc('main.files_selected')
+              : $tc('main.files_selected', uploadedFiles.length)
🤖 Prompt for AI Agents
In src/components/widgets/FileUpload.vue around lines 33 to 40, the fallback
$tc('main.files_selected') call is missing the count argument which can break
pluralization; update both $tc calls to pass the count (use
uploadedFiles.length) and ensure the pluralization options object or numeric
count is provided consistently so plural forms render correctly across locales.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant