Claude ec9ace9c54 docs: add native Japanese translation of ECC documentation (ja-JP)
Translate everything-claude-code repository to Japanese including:
- 17 root documentation files
- 60 agent documentation files
- 80 command documentation files
- 99 rule files across 18 language directories (common, angular, arkts, cpp, csharp, dart, fsharp, golang, java, kotlin, perl, php, python, ruby, rust, swift, typescript, web)
- 199 skill documentation files

Total: 455 files translated to Japanese with:
- Consistent terminology glossary applied throughout
- YAML field names preserved in English (name, description, etc.)
- Code blocks and examples untouched (comments translated)
- Markdown structure and relative links preserved
- Professional translation maintaining technical accuracy

This translation expands ECC accessibility to Japanese-speaking developers and teams.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-17 02:31:40 -04:00

8.0 KiB
Raw Blame History

paths
paths
**/*.component.ts
**/*.component.html
**/*.service.ts
**/*.store.ts
**/*.routes.ts

Angular パターン

このファイルは common/patterns.md を Angular 固有のコンテンツで拡張します。

Smart / Dumb コンポーネント分離

Smartコンテナコンポーネントはデータ取得と状態を所有します。Dumbプレゼンテーションコンポーネントは入力の受け取りと出力の発行のみを行い、サービスの注入は行いません。

// Smart — データを所有
@Component({ standalone: true, changeDetection: ChangeDetectionStrategy.OnPush })
export class UserPageComponent {
  private userService = inject(UserService);
  user = toSignal(this.userService.getUser(this.userId));
}
<!-- Dumb — 純粋なプレゼンテーション -->
<app-user-card [user]="user()" (select)="onSelect($event)" />

サービスレイヤー

サービスがすべてのデータアクセスとビジネスロジックを所有します。コンポーネントは委譲のみ — コンポーネント内に HttpClient を配置しないでください。

@Injectable({ providedIn: 'root' })
export class UserService {
  private http = inject(HttpClient);

  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users');
  }
}

resource を使用した非同期データ

リアクティブな非同期フェッチには resource() を使用してください。単純なデータ読み込みには手動の RxJS パイプラインよりも優先してください:

export class UserDetailComponent {
  userId = input.required<string>();

  userResource = resource({
    request: () => ({ id: this.userId() }),
    loader: ({ request }) =>
      firstValueFrom(inject(UserService).getUser(request.id)),
  });
}

状態へのアクセス: userResource.value()userResource.isLoading()userResource.error()userResource.reload()

シグナル状態パターン

// ローカルの可変状態
count = signal(0);

// 派生(複製しない)
doubled = computed(() => this.count() * 2);

// ソースとともにリセットされる書き込み可能な派生状態
selectedItem = linkedSignal(() => this.items()[0]);

// Observable からシグナルへのブリッジ
users = toSignal(this.userService.getUsers(), { initialValue: [] });

派生値を別のシグナルに格納しないでください — computed を使用してください。シグナルの同期に effect を使用しないでください — computed または linkedSignal を使用してください。

サブスクリプションのクリーンアップ

すべての手動サブスクリプションには takeUntilDestroyed() を使用してください。新しいコードでは手動の ngOnDestroy + Subject + takeUntil を使用しないでください。

export class UserComponent {
  private destroyRef = inject(DestroyRef);

  ngOnInit() {
    this.userService.updates$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(update => this.handleUpdate(update));
  }
}

ルーティング

ルート定義

// app.routes.ts
export const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'admin',
    canMatch: [authGuard],           // CanMatch はチャンクの読み込み自体を防止
    loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES),
  },
  {
    path: 'users/:id',
    resolve: { user: userResolver },
    component: UserDetailComponent,
  },
];
  • 未認証ユーザーに対してルートモジュールを読み込まないようにする場合は canMatchcanActivate より優先
  • すべての機能モジュールを loadChildren で遅延読み込み
  • コンポーネント内のローディング状態を回避するため resolve でデータをプリフェッチ

関数型ガード

export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  return auth.isAuthenticated()
    ? true
    : inject(Router).createUrlTree(['/login']);
};

データリゾルバ

export const userResolver: ResolveFn<User> = (route) => {
  return inject(UserService).getUser(route.paramMap.get('id')!);
};

ビュートランジション

View Transitions API でスムーズなルート遷移を有効化:

// app.config.ts
provideRouter(routes, withViewTransitions())

依存性注入パターン

スコープ付きプロバイダ

サービスがシングルトンであるべきでない場合、コンポーネントまたはルートレベルで提供してください:

@Component({
  providers: [UserEditService],   // このコンポーネントサブツリーにスコープ
})
export class UserEditComponent {}

InjectionToken

export const CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');

// プロバイダ内:
{ provide: CONFIG, useValue: appConfig }
{ provide: CONFIG, useFactory: () => loadConfig(), deps: [] }

// 使用:
private config = inject(CONFIG);

viewProvidersproviders

  • providers: コンポーネントとそのすべてのコンテンツ子要素で利用可能
  • viewProviders: コンポーネント自身のビューでのみ利用可能(投影されたコンテンツでは不可)

HTTP インターセプター

認証、エラーハンドリング、リトライには関数型インターセプターv15+)を使用してください:

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).token();
  if (!token) return next(req);
  return next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }));
};

app.config.ts で登録:

provideHttpClient(withInterceptors([authInterceptor, errorInterceptor]))

RxJS オペレータ

  • switchMap — 検索、ナビゲーション(前のリクエストをキャンセル)
  • mergeMap — 独立した並列リクエスト
  • exhaustMap — フォーム送信(完了するまで無視)
  • 常に catchError でエラーを処理 — ストリームを暗黙的に死なせない
search$ = this.query$.pipe(
  debounceTime(300),
  distinctUntilChanged(),
  switchMap(q => this.service.search(q).pipe(catchError(() => of([])))),
);

フォーム

プロジェクトの既存のフォーム戦略に合わせてください。v21+ の新規アプリにはシグナルフォームを優先してください。

// Reactive Forms — 複雑なフォームの標準
export class UserFormComponent {
  private fb = inject(FormBuilder);

  form = this.fb.group({
    name: ['', Validators.required],
    email: ['', [Validators.required, Validators.email]],
  });
}

レンダリング戦略

  • CSR(デフォルト): 標準 SPA
  • SSR + ハイドレーション: ng add @angular/ssr — FCP と SEO を改善
  • SSGプリレンダリング: コンテンツの多いルート向けにビルド時に静的ページを生成

SSR を使用する場合、windowdocumentlocalStorage を直接使用しないでください — isPlatformBrowser または DOCUMENT トークンを使用してください。

アクセシビリティ

ヘッドレスでアクセシブルなコンポーネントAccordion、Listbox、Combobox、Menu、Tabs、Toolbar、Tree、Gridには Angular CDK を使用してください。ARIA 属性を手動で管理するのではなく、スタイルを適用してください:

[aria-selected="true"] { background: var(--color-selected); }

スキルリファレンス

シグナル、フォーム、ルーティング、DI、SSR、アクセシビリティパターンの詳細なガイダンスについては、スキル: angular-developer を参照してください。