From 5e069b42a3f2c8c90cef323a80b6ab12cf80e1c0 Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Sat, 20 Jul 2024 13:37:01 +0900 Subject: [PATCH 1/3] chore: copy file --- .../di/hierarchical-dependency-injection.md | 1180 +++++++++++++++++ 1 file changed, 1180 insertions(+) create mode 100644 adev-ja/src/content/guide/di/hierarchical-dependency-injection.md diff --git a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md new file mode 100644 index 0000000000..75465edfb4 --- /dev/null +++ b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md @@ -0,0 +1,1180 @@ +# Hierarchical injectors + +Injectors in Angular have rules that you can leverage to achieve the desired visibility of injectables in your applications. +By understanding these rules, you can determine whether to declare a provider at the application level, in a Component, or in a Directive. + +The applications you build with Angular can become quite large, and one way to manage this complexity is to split up the application into a well-defined tree of components. + +There can be sections of your page that work in a completely independent way than the rest of the application, with its own local copies of the services and other dependencies that it needs. +Some of the services that these sections of the application use might be shared with other parts of the application, or with parent components that are further up in the component tree, while other dependencies are meant to be private. + +With hierarchical dependency injection, you can isolate sections of the application and give them their own private dependencies not shared with the rest of the application, or have parent components share certain dependencies with its child components only but not with the rest of the component tree, and so on. Hierarchical dependency injection enables you to share dependencies between different parts of the application only when and if you need to. + +## Types of injector hierarchies + +Angular has two injector hierarchies: + +| Injector hierarchies | Details | +|:--- |:--- | +| `EnvironmentInjector` hierarchy | Configure an `ElementInjector` in this hierarchy using `@Injectable()` or `providers` array in `ApplicationConfig`. | +| `ElementInjector` hierarchy | Created implicitly at each DOM element. An `ElementInjector` is empty by default unless you configure it in the `providers` property on `@Directive()` or `@Component()`. | + + +For `NgModule` based applications, you can provide dependencies with the `ModuleInjector` hierarchy using an `@NgModule()` or `@Injectable()` annotation. + + +### `EnvironmentInjector` + +The `EnvironmentInjector` can be configured in one of two ways by using: + +* The `@Injectable()` `providedIn` property to refer to `root` or `platform` +* The `ApplicationConfig` `providers` array + + + +Using the `@Injectable()` `providedIn` property is preferable to using the `ApplicationConfig` `providers` array. With `@Injectable()` `providedIn`, optimization tools can perform tree-shaking, which removes services that your application isn't using. This results in smaller bundle sizes. + +Tree-shaking is especially useful for a library because the application which uses the library may not have a need to inject it. + + + +`EnvironmentInjector` is configured by the `ApplicationConfig.providers`. + +Provide services using `providedIn` of `@Injectable()` as follows: + + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' // <--provides this service in the root EnvironmentInjector +}) +export class ItemService { + name = 'telephone'; +} + + + +The `@Injectable()` decorator identifies a service class. +The `providedIn` property configures a specific `EnvironmentInjector`, here `root`, which makes the service available in the `root` `EnvironmentInjector`. + +### ModuleInjector + +In the case of `NgModule` based applications, the ModuleInjector can be configured in one of two ways by using: + +* The `@Injectable()` `providedIn` property to refer to `root` or `platform` +* The `@NgModule()` `providers` array + +`ModuleInjector` is configured by the `@NgModule.providers` and `NgModule.imports` property. `ModuleInjector` is a flattening of all the providers arrays that can be reached by following the `NgModule.imports` recursively. + +Child `ModuleInjector` hierarchies are created when lazy loading other `@NgModules`. + +### Platform injector + +There are two more injectors above `root`, an additional `EnvironmentInjector` and `NullInjector()`. + +Consider how Angular bootstraps the application with the following in `main.ts`: + + +bootstrapApplication(AppComponent, appConfig); + + +The `bootstrapApplication()` method creates a child injector of the platform injector which is configured by the `ApplicationConfig` instance. +This is the `root` `EnvironmentInjector`. + +The `platformBrowserDynamic()` method creates an injector configured by a `PlatformModule`, which contains platform-specific dependencies. +This allows multiple applications to share a platform configuration. +For example, a browser has only one URL bar, no matter how many applications you have running. +You can configure additional platform-specific providers at the platform level by supplying `extraProviders` using the `platformBrowser()` function. + +The next parent injector in the hierarchy is the `NullInjector()`, which is the top of the tree. +If you've gone so far up the tree that you are looking for a service in the `NullInjector()`, you'll get an error unless you've used `@Optional()` because ultimately, everything ends at the `NullInjector()` and it returns an error or, in the case of `@Optional()`, `null`. +For more information on `@Optional()`, see the [`@Optional()` section](#optional) of this guide. + +The following diagram represents the relationship between the `root` `ModuleInjector` and its parent injectors as the previous paragraphs describe. + +```mermaid +stateDiagram-v2 + elementInjector: EnvironmentInjector\n(configured by Angular)\nhas special things like DomSanitizer => providedIn 'platform' + rootInjector: root EnvironmentInjector\n(configured by AppConfig)\nhas things for your app => bootstrapApplication(..., AppConfig) + nullInjector: NullInjector\nalways throws an error unless\nyou use @Optional() + + direction BT + rootInjector --> elementInjector + elementInjector --> nullInjector +``` + +While the name `root` is a special alias, other `EnvironmentInjector` hierarchies don't have aliases. +You have the option to create `EnvironmentInjector` hierarchies whenever a dynamically loaded component is created, such as with the Router, which will create child `EnvironmentInjector` hierarchies. + +All requests forward up to the root injector, whether you configured it with the `ApplicationConfig` instance passed to the `bootstrapApplication()` method, or registered all providers with `root` in their own services. + + + +If you configure an app-wide provider in the `ApplicationConfig` of `bootstrapApplication`, it overrides one configured for `root` in the `@Injectable()` metadata. +You can do this to configure a non-default provider of a service that is shared with multiple applications. + +Here is an example of the case where the component router configuration includes a non-default [location strategy](guide/routing#location-strategy) by listing its provider in the `providers` list of the `ApplicationConfig`. + +```ts +providers: [ + { provide: LocationStrategy, useClass: HashLocationStrategy } +] +``` + +For `NgModule` based applications, configure app-wide providers in the `AppModule` `providers`. + + + +### `ElementInjector` + +Angular creates `ElementInjector` hierarchies implicitly for each DOM element. + +Providing a service in the `@Component()` decorator using its `providers` or `viewProviders` property configures an `ElementInjector`. +For example, the following `TestComponent` configures the `ElementInjector` by providing the service as follows: + + +@Component({ + 
 + providers: [{ provide: ItemService, useValue: { name: 'lamp' } }] +}) +export class TestComponent + + +HELPFUL: See the [resolution rules](#resolution-rules) section to understand the relationship between the `EnvironmentInjector` tree, the `ModuleInjector` and the `ElementInjector` tree. + +When you provide services in a component, that service is available by way of the `ElementInjector` at that component instance. +It may also be visible at child component/directives based on visibility rules described in the [resolution rules](#resolution-rules) section. + +When the component instance is destroyed, so is that service instance. + +#### `@Directive()` and `@Component()` + +A component is a special type of directive, which means that just as `@Directive()` has a `providers` property, `@Component()` does too. +This means that directives as well as components can configure providers, using the `providers` property. +When you configure a provider for a component or directive using the `providers` property, that provider belongs to the `ElementInjector` of that component or directive. +Components and directives on the same element share an injector. + +## Resolution rules + +When resolving a token for a component/directive, Angular resolves it in two phases: + +1. Against its parents in the `ElementInjector` hierarchy. +2. Against its parents in the `EnvironmentInjector` hierarchy. + +When a component declares a dependency, Angular tries to satisfy that dependency with its own `ElementInjector`. +If the component's injector lacks the provider, it passes the request up to its parent component's `ElementInjector`. + +The requests keep forwarding up until Angular finds an injector that can handle the request or runs out of ancestor `ElementInjector` hierarchies. + +If Angular doesn't find the provider in any `ElementInjector` hierarchies, it goes back to the element where the request originated and looks in the `EnvironmentInjector` hierarchy. +If Angular still doesn't find the provider, it throws an error. + +If you have registered a provider for the same DI token at different levels, the first one Angular encounters is the one it uses to resolve the dependency. +If, for example, a provider is registered locally in the component that needs a service, +Angular doesn't look for another provider of the same service. + +HELPFUL: For `NgModule` based applications, Angular will search the `ModuleInjector` hierarchy if it cannot find a provider in the `ElementInjector` hierarchies. + +## Resolution modifiers + +Angular's resolution behavior can be modified with `@Optional()`, `@Self()`, `@SkipSelf()` and `@Host()`. +Import each of them from `@angular/core` and use each in the component class constructor or in the `inject` configuration when you inject your service. + +### Types of modifiers + +Resolution modifiers fall into three categories: + +* What to do if Angular doesn't find what you're looking for, that is `@Optional()` +* Where to start looking, that is `@SkipSelf()` +* Where to stop looking, `@Host()` and `@Self()` + +By default, Angular always starts at the current `Injector` and keeps searching all the way up. +Modifiers allow you to change the starting, or _self_, location and the ending location. + +Additionally, you can combine all of the modifiers except: + +* `@Host()` and `@Self()` +* `@SkipSelf()` and `@Self()`. + +### `@Optional()` + +`@Optional()` allows Angular to consider a service you inject to be optional. +This way, if it can't be resolved at runtime, Angular resolves the service as `null`, rather than throwing an error. +In the following example, the service, `OptionalService`, isn't provided in the service, `ApplicationConfig`, `@NgModule()`, or component class, so it isn't available anywhere in the app. + + +export class OptionalComponent { + constructor(@Optional() public optional?: OptionalService) {} +} + + +### `@Self()` + +Use `@Self()` so that Angular will only look at the `ElementInjector` for the current component or directive. + +A good use case for `@Self()` is to inject a service but only if it is available on the current host element. +To avoid errors in this situation, combine `@Self()` with `@Optional()`. + +For example, in the following `SelfComponent`, notice the injected `LeafService` in the constructor. + + +@Component({ + selector: 'app-self-no-data', + templateUrl: './self-no-data.component.html', + styleUrls: ['./self-no-data.component.css'] +}) +export class SelfNoDataComponent { + constructor(@Self() @Optional() public leaf?: LeafService) { } +} + + +In this example, there is a parent provider and injecting the service will return the value, however, injecting the service with `@Self()` and `@Optional()` will return `null` because `@Self()` tells the injector to stop searching in the current host element. + +Another example shows the component class with a provider for `FlowerService`. +In this case, the injector looks no further than the current `ElementInjector` because it finds the `FlowerService` and returns the tulip 🌷. + + + +### `@SkipSelf()` + +`@SkipSelf()` is the opposite of `@Self()`. +With `@SkipSelf()`, Angular starts its search for a service in the parent `ElementInjector`, rather than in the current one. +So if the parent `ElementInjector` were using the fern 🌿 value for `emoji`, but you had maple leaf 🍁 in the component's `providers` array, Angular would ignore maple leaf 🍁 and use fern 🌿. + +To see this in code, assume that the following value for `emoji` is what the parent component were using, as in this service: + + +export class LeafService { + emoji = '🌿'; +} + + +Imagine that in the child component, you had a different value, maple leaf 🍁 but you wanted to use the parent's value instead. +This is when you'd use `@SkipSelf()`: + + +@Component({ + selector: 'app-skipself', + templateUrl: './skipself.component.html', + styleUrls: ['./skipself.component.css'], + // Angular would ignore this LeafService instance + providers: [{ provide: LeafService, useValue: { emoji: '🍁' } }] +}) +export class SkipselfComponent { + // Use @SkipSelf() in the constructor + constructor(@SkipSelf() public leaf: LeafService) { } +} + + +In this case, the value you'd get for `emoji` would be fern 🌿, not maple leaf 🍁. + +#### `@SkipSelf()` with `@Optional()` + +Use `@SkipSelf()` with `@Optional()` to prevent an error if the value is `null`. + +In the following example, the `Person` service is injected in the constructor. +`@SkipSelf()` tells Angular to skip the current injector and `@Optional()` will prevent an error should the `Person` service be `null`. + + +class Person { + constructor(@Optional() @SkipSelf() parent?: Person) {} +} + + +### `@Host()` + + + +`@Host()` lets you designate a component as the last stop in the injector tree when searching for providers. + +Even if there is a service instance further up the tree, Angular won't continue looking. +Use `@Host()` as follows: + + +@Component({ + selector: 'app-host', + templateUrl: './host.component.html', + styleUrls: ['./host.component.css'], + // provide the service + providers: [{ provide: FlowerService, useValue: { emoji: '🌷' } }] +}) +export class HostComponent { + // use @Host() in the constructor when injecting the service + constructor(@Host() @Optional() public flower?: FlowerService) { } +} + + +Since `HostComponent` has `@Host()` in its constructor, no matter what the parent of `HostComponent` might have as a `flower.emoji` value, the `HostComponent` will use tulip 🌷. + +## Logical structure of the template + +When you provide services in the component class, services are visible within the `ElementInjector` tree relative to where and how you provide those services. + +Understanding the underlying logical structure of the Angular template will give you a foundation for configuring services and in turn control their visibility. + +Components are used in your templates, as in the following example: + + + + ; + + + +HELPFUL: Usually, you declare the components and their templates in separate files. +For the purposes of understanding how the injection system works, it is useful to look at them from the point of view of a combined logical tree. +The term _logical_ distinguishes it from the render tree, which is your application's DOM tree. +To mark the locations of where the component templates are located, this guide uses the `<#VIEW>` pseudo-element, which doesn't actually exist in the render tree and is present for mental model purposes only. + +The following is an example of how the `` and `` view trees are combined into a single logical tree: + + + + <#VIEW> + + <#VIEW> + 
content goes here
 + + + + + + +Understanding the idea of the `<#VIEW>` demarcation is especially significant when you configure services in the component class. + +## Example: Providing services in `@Component()` + +How you provide services using a `@Component()` (or `@Directive()`) decorator determines their visibility. +The following sections demonstrate `providers` and `viewProviders` along with ways to modify service visibility with `@SkipSelf()` and `@Host()`. + +A component class can provide services in two ways: + +| Arrays | Details | +|:--- |:--- | +| With a `providers` array | `@Component({ providers: [SomeService] })` | +| With a `viewProviders` array | `@Component({ viewProviders: [SomeService] })` | + +In the examples below, you will see the logical tree of an Angular application. +To illustrate how the injector works in the context of templates, the logical tree will represent the HTML structure of the application. +For example, the logical tree will show that `` is a direct children of ``. + +In the logical tree, you will see special attributes: `@Provide`, `@Inject`, and `@ApplicationConfig`. +These aren't real attributes but are here to demonstrate what is going on under the hood. + +| Angular service attribute | Details | +|:--- |:--- | +| `@Inject(Token)=>Value` | If `Token` is injected at this location in the logical tree, its value would be `Value`. | +| `@Provide(Token=Value)` | Indicates that `Token` is provided with `Value` at this location in the logical tree. | +| `@ApplicationConfig` | Demonstrates that a fallback `EnvironmentInjector` should be used at this location. | + +### Example app structure + +The example application has a `FlowerService` provided in `root` with an `emoji` value of red hibiscus 🌺. + + +@Injectable({ + providedIn: 'root' +}) +export class FlowerService { + emoji = '🌺'; +} + + +Consider an application with only an `AppComponent` and a `ChildComponent`. +The most basic rendered view would look like nested HTML elements such as the following: + + + + + + + + + + +However, behind the scenes, Angular uses a logical view representation as follows when resolving injection requests: + + + + <#VIEW> + + <#VIEW> + + + + + + +The `<#VIEW>` here represents an instance of a template. +Notice that each component has its own `<#VIEW>`. + +Knowledge of this structure can inform how you provide and inject your services, and give you complete control of service visibility. + +Now, consider that `` injects the `FlowerService`: + + +export class AppComponent { + constructor(public flower: FlowerService) {} +} + + +Add a binding to the `` template to visualize the result: + + +

Emoji from FlowerService: {{flower.emoji}}

+
+ +The output in the view would be: + + +Emoji from FlowerService: 🌺 + + +In the logical tree, this would be represented as follows: + + +"🌺"> + <#VIEW> +

Emoji from FlowerService: {{flower.emoji}} (🌺)

+ + <#VIEW> + + + +
+ +
+ +When `` requests the `FlowerService`, it is the injector's job to resolve the `FlowerService` token. +The resolution of the token happens in two phases: + +1. The injector determines the starting location in the logical tree and an ending location of the search. + The injector begins with the starting location and looks for the token at each view level in the logical tree. + If the token is found it is returned. + +1. If the token is not found, the injector looks for the closest parent `EnvironmentInjector` to delegate the request to. + +In the example case, the constraints are: + +1. Start with `<#VIEW>` belonging to `` and end with ``. + + * Normally the starting point for search is at the point of injection. + However, in this case `` is a component. `@Component`s are special in that they also include their own `viewProviders`, which is why the search starts at `<#VIEW>` belonging to ``. + This would not be the case for a directive matched at the same location. + * The ending location happens to be the same as the component itself, because it is the topmost component in this application. + +1. The `ElementInjector` provided by the `ApplicationConfig` acts as the fallback injector when the injection token can't be found in the `ElementInjector` hierarchies. + +### Using the `providers` array + +Now, in the `ChildComponent` class, add a provider for `FlowerService` to demonstrate more complex resolution rules in the upcoming sections: + + +@Component({ + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // use the providers array to provide a service + providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }] +}) +export class ChildComponent { + // inject the service + constructor( public flower: FlowerService) { } +} + + +Now that the `FlowerService` is provided in the `@Component()` decorator, when the `` requests the service, the injector has only to look as far as the `ElementInjector` in the ``. +It won't have to continue the search any further through the injector tree. + +The next step is to add a binding to the `ChildComponent` template. + + +

Emoji from FlowerService: {{flower.emoji}}

+
+ +To render the new values, add `` to the bottom of the `AppComponent` template so the view also displays the sunflower: + + +Child Component +Emoji from FlowerService: 🌻 + + +In the logical tree, this is represented as follows: + + + +"🌺"> + <#VIEW> +

Emoji from FlowerService: {{flower.emoji}} (🌺)

+ "🌻"> + <#VIEW> +

Child Component

+

Emoji from FlowerService: {{flower.emoji}} (🌻)

+ +
+ +
+ +
+ +When `` requests the `FlowerService`, the injector begins its search at the `<#VIEW>` belonging to `` \(`<#VIEW>` is included because it is injected from `@Component()`\) and ends with ``. +In this case, the `FlowerService` is resolved in the `providers` array with sunflower 🌻 of the ``. +The injector doesn't have to look any further in the injector tree. +It stops as soon as it finds the `FlowerService` and never sees the red hibiscus 🌺. + +### Using the `viewProviders` array + +Use the `viewProviders` array as another way to provide services in the `@Component()` decorator. +Using `viewProviders` makes services visible in the `<#VIEW>`. + +HELPFUL: The steps are the same as using the `providers` array, with the exception of using the `viewProviders` array instead. + +For step-by-step instructions, continue with this section. +If you can set it up on your own, skip ahead to [Modifying service availability](#visibility-of-provided-tokens). + +For demonstration, we are building an `AnimalService` to demonstrate `viewProviders`. +First, create an `AnimalService` with an `emoji` property of whale 🐳: + + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class AnimalService { + emoji = '🐳'; +} + + +Following the same pattern as with the `FlowerService`, inject the `AnimalService` in the `AppComponent` class: + + +export class AppComponent { + constructor( + public flower: FlowerService, + public animal: AnimalService) {} +} + + +HELPFUL: You can leave all the `FlowerService` related code in place as it will allow a comparison with the `AnimalService`. + +Add a `viewProviders` array and inject the `AnimalService` in the `` class, too, but give `emoji` a different value. +Here, it has a value of dog 🐶. + + +@Component({ + selector: 'app-child', + templateUrl: './child.component.html', + styleUrls: ['./child.component.css'], + // provide services + providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }], + viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }] +}) +export class ChildComponent { + // inject service + constructor( public flower: FlowerService, public animal: AnimalService) { } +... +} + + +Add bindings to the `ChildComponent` and the `AppComponent` templates. +In the `ChildComponent` template, add the following binding: + + +

Emoji from AnimalService: {{animal.emoji}}

+
+ +Additionally, add the same to the `AppComponent` template: + + +

Emoji from AnimalService: {{animal.emoji}}

s +
+ +Now you should see both values in the browser: + + + +AppComponent +Emoji from AnimalService: 🐳 + +Child Component +Emoji from AnimalService: 🐶 + + + +The logic tree for this example of `viewProviders` is as follows: + + + +"🐳"> + <#VIEW> + + <#VIEW @Provide(AnimalService="🐶") + @Inject(AnimalService=>"🐶")> + +

Emoji from AnimalService: {{animal.emoji}} (🐶)

+ +
+ +
+ +
+ +Just as with the `FlowerService` example, the `AnimalService` is provided in the `` `@Component()` decorator. +This means that since the injector first looks in the `ElementInjector` of the component, it finds the `AnimalService` value of dog 🐶. +It doesn't need to continue searching the `ElementInjector` tree, nor does it need to search the `ModuleInjector`. + +### `providers` vs. `viewProviders` + +The `viewProviders` field is conceptually similar to `providers`, but there is one notable difference. +Configured providers in `viewProviders` are not visible to projected content that ends up as a logical children of the component. + +To see the difference between using `providers` and `viewProviders`, add another component to the example and call it `InspectorComponent`. +`InspectorComponent` will be a child of the `ChildComponent`. +In `inspector.component.ts`, inject the `FlowerService` and `AnimalService` in the constructor: + + +export class InspectorComponent { + constructor(public flower: FlowerService, public animal: AnimalService) { } +} + + +You do not need a `providers` or `viewProviders` array. +Next, in `inspector.component.html`, add the same markup from previous components: + + +

Emoji from FlowerService: {{flower.emoji}}

+

Emoji from AnimalService: {{animal.emoji}}

+
+ +Remember to add the `InspectorComponent` to the `ChildComponent` `imports` array. + + +@Component({ + ... + imports: [InspectorComponent] +}) + + + +Next, add the following to `child.component.html`: + + +... + +
+

Content projection

+ +
+

Inside the view

+ + +
+ +`` allows you to project content, and `` inside the `ChildComponent` template makes the `InspectorComponent` a child component of `ChildComponent`. + +Next, add the following to `app.component.html` to take advantage of content projection. + + + + + + + +The browser now renders the following, omitting the previous examples for brevity: + + +... +Content projection + +Emoji from FlowerService: 🌻 +Emoji from AnimalService: 🐳 + +Emoji from FlowerService: 🌻 +Emoji from AnimalService: 🐶 + + + +These four bindings demonstrate the difference between `providers` and `viewProviders`. +Remember that the dog emoji 🐶 is declared inside the `<#VIEW>` of `ChildComponent` and isn't visible to the projected content. +Instead, the projected content sees the whale 🐳. + +However, in the next output section though, the `InspectorComponent` is an actual child component of `ChildComponent`, `InspectorComponent` is inside the `<#VIEW>`, so when it asks for the `AnimalService`, it sees the dog 🐶. + +The `AnimalService` in the logical tree would look like this: + + + +"🐳"> + <#VIEW> + + <#VIEW @Provide(AnimalService="🐶") + @Inject(AnimalService=>"🐶")> + +

Emoji from AnimalService: {{animal.emoji}} (🐶)

+ +
+

Content projection

+ "🐳"> +

Emoji from AnimalService: {{animal.emoji}} (🐳)

+
+
+ + + <#VIEW @Inject(AnimalService) animal=>"🐶"> +

Emoji from AnimalService: {{animal.emoji}} (🐶)

+ +
+ +
+ +
+ +
+ +The projected content of `` sees the whale 🐳, not the dog 🐶, because the dog 🐶 is inside the `` `<#VIEW>`. +The `` can only see the dog 🐶 if it is also within the `<#VIEW>`. + +### Visibility of provided tokens + +Visibility decorators influence where the search for the injection token begins and ends in the logic tree. +To do this, place visibility decorators at the point of injection, that is, the `constructor()`, rather than at a point of declaration. + +To alter where the injector starts looking for `FlowerService`, add `@SkipSelf()` to the `` `@Inject` declaration where `FlowerService` is injected. +This declaration is in the `` constructor as shown in `child.component.ts`: + + +constructor(@SkipSelf() public flower: FlowerService) { } + + +With `@SkipSelf()`, the `` injector doesn't look to itself for the `FlowerService`. +Instead, the injector starts looking for the `FlowerService` at the `ElementInjector` of the ``, where it finds nothing. +Then, it goes back to the `` `ModuleInjector` and finds the red hibiscus 🌺 value, which is available because `` and `` share the same `ModuleInjector`. +The UI renders the following: + + + +Emoji from FlowerService: 🌺 + + + +In a logical tree, this same idea might look like this: + + + +"🌺"> + <#VIEW> + + <#VIEW @Inject(FlowerService, SkipSelf)=>"🌺"> + + + + + + + + +Though `` provides the sunflower 🌻, the application renders the red hibiscus 🌺 because `@SkipSelf()` causes the current injector (`app-child`) to skip itself and look to its parent. + +If you now add `@Host()` (in addition to the `@SkipSelf()`), the result will be `null`. +This is because `@Host()` limits the upper bound of the search to the `app-child` `<#VIEW>`. +Here's the idea in the logical tree: + + + +"🌺"> + <#VIEW> + + <#VIEW @Inject(FlowerService, @SkipSelf, @Host, @Optional)=>null> + + + + + + + +Here, the services and their values are the same, but `@Host()` stops the injector from looking any further than the `<#VIEW>` for `FlowerService`, so it doesn't find it and returns `null`. + +### `@SkipSelf()` and `viewProviders` + +Remember, `` provides the `AnimalService` in the `viewProviders` array with the value of dog 🐶. +Because the injector has only to look at the `ElementInjector` of the `` for the `AnimalService`, it never sees the whale 🐳. + +As in the `FlowerService` example, if you add `@SkipSelf()` to the constructor for the `AnimalService`, the injector won't look in the `ElementInjector` of the current `` for the `AnimalService`. +Instead, the injector will begin at the `` `ElementInjector`. + + +@Component({ + standalone: true, + selector: 'app-child', + 
 + viewProviders: [ + { provide: AnimalService, useValue: { emoji: '🐶' } }, + ], +}) + + +The logical tree looks like this with `@SkipSelf()` in ``: + + + +"🐳")> + <#VIEW> + + <#VIEW @Provide(AnimalService="🐶") + @Inject(AnimalService, SkipSelf=>"🐳")> + + + + + + + + +With `@SkipSelf()` in the ``, the injector begins its search for the `AnimalService` in the `` `ElementInjector` and finds whale 🐳. + +### `@Host()` and `viewProviders` + +If you just use `@Host()` for the injection of `AnimalService`, the result is dog 🐶 because the injector finds the `AnimalService` in the `` `<#VIEW>` itself. +The `ChildComponent` configures the `viewProviders` so that the dog emoji is provided as `AnimalService` value. +You can also see `@Host()` in the constructor: + + +@Component({ + standalone: true + selector: 'app-child', + 
 + viewProviders: [ + { provide: AnimalService, useValue: { emoji: '🐶' } }, + ] +}) +export class ChildComponent { + constructor(@Host() public animal: AnimalService) { } +} + + +`@Host()` causes the injector to look until it encounters the edge of the `<#VIEW>`. + + + +"🐳")> + <#VIEW> + + <#VIEW @Provide(AnimalService="🐶") + @Inject(AnimalService, @Host=>"🐶")> + + + + + + + +Add a `viewProviders` array with a third animal, hedgehog 🦔, to the `app.component.ts` `@Component()` metadata: + + +@Component({ + standalone: true, + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: [ './app.component.css' ], + viewProviders: [ + { provide: AnimalService, useValue: { emoji: '🦔' } }, + ], +}) + + + +Next, add `@SkipSelf()` along with `@Host()` to the constructor for the `AnimalService` injection in `child.component.ts`. +Here are `@Host()` and `@SkipSelf()` in the `` constructor: + + +export class ChildComponent { + + constructor( + @Host() @SkipSelf() public animal: AnimalService) { } +} + + + + + +When `@Host()` and `@SkipSelf()` were applied to the `FlowerService`, which is in the `providers` array, the result was `null` because `@SkipSelf()` starts its search in the `` injector, but `@Host()` stops searching at `<#VIEW>` —where there is no `FlowerService` +In the logical tree, you can see that the `FlowerService` is visible in ``, not its `<#VIEW>`. + +However, the `AnimalService`, which is provided in the `AppComponent` `viewProviders` array, is visible. + +The logical tree representation shows why this is: + + + +"🐳")> + <#VIEW @Provide(AnimalService="🦔") + @Inject(AnimalService, @Optional)=>"🦔"> + + + <#VIEW @Provide(AnimalService="🐶") + @Inject(AnimalService, @SkipSelf, @Host, @Optional)=>"🦔"> + + + + + + + + +`@SkipSelf()`, causes the injector to start its search for the `AnimalService` at the ``, not the ``, where the request originates, and `@Host()` stops the search at the `` `<#VIEW>`. +Since `AnimalService` is provided by way of the `viewProviders` array, the injector finds hedgehog 🦔 in the `<#VIEW>`. + +## Example: `ElementInjector` use cases + +The ability to configure one or more providers at different levels opens up useful possibilities. + +### Scenario: service isolation + +Architectural reasons may lead you to restrict access to a service to the application domain where it belongs. +For example, consider we build a `VillainsListComponent` that displays a list of villains. +It gets those villains from a `VillainsService`. + +If you provide `VillainsService` in the root `AppModule`, it will make `VillainsService` visible everywhere in the application. +If you later modify the `VillainsService`, you could break something in other components that started depending this service by accident. + +Instead, you should provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this: + + +@Component({ + selector: 'app-villains-list', + templateUrl: './villains-list.component.html', + providers: [VillainsService] +}) +export class VillainsListComponent {} + + +By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else, the service becomes available only in the `VillainsListComponent` and its subcomponent tree. + +`VillainService` is a singleton with respect to `VillainsListComponent` because that is where it is declared. +As long as `VillainsListComponent` does not get destroyed it will be the same instance of `VillainService` but if there are multiple instances of `VillainsListComponent`, then each instance of `VillainsListComponent` will have its own instance of `VillainService`. + +### Scenario: multiple edit sessions + +Many applications allow users to work on several open tasks at the same time. +For example, in a tax preparation application, the preparer could be working on several tax returns, switching from one to the other throughout the day. + +To demonstrate that scenario, imagine a `HeroListComponent` that displays a list of super heroes. + +To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return. +Each selected hero tax return opens in its own component and multiple returns can be open at the same time. + +Each tax return component has the following characteristics: + +* Is its own tax return editing session +* Can change a tax return without affecting a return in another component +* Has the ability to save the changes to its tax return or cancel them + +Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes. +That would be a straightforward task for a hero tax return. +In the real world, with a rich tax return data model, the change management would be tricky. +You could delegate that management to a helper service, as this example does. + +The `HeroTaxReturnService` caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it. +It also delegates to the application-wide singleton `HeroService`, which it gets by injection. + + +import { Injectable } from '@angular/core'; +import { HeroTaxReturn } from './hero'; +import { HeroesService } from './heroes.service'; + +@Injectable() +export class HeroTaxReturnService { + private currentTaxReturn!: HeroTaxReturn; + private originalTaxReturn!: HeroTaxReturn; + + constructor(private heroService: HeroesService) {} + + set taxReturn(htr: HeroTaxReturn) { + this.originalTaxReturn = htr; + this.currentTaxReturn = htr.clone(); + } + + get taxReturn(): HeroTaxReturn { + return this.currentTaxReturn; + } + + restoreTaxReturn() { + this.taxReturn = this.originalTaxReturn; + } + + saveTaxReturn() { + this.taxReturn = this.currentTaxReturn; + this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe(); + } +} + + +Here is the `HeroTaxReturnComponent` that makes use of `HeroTaxReturnService`. + + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { HeroTaxReturn } from './hero'; +import { HeroTaxReturnService } from './hero-tax-return.service'; + +@Component({ + selector: 'app-hero-tax-return', + templateUrl: './hero-tax-return.component.html', + styleUrls: [ './hero-tax-return.component.css' ], + providers: [ HeroTaxReturnService ] +}) +export class HeroTaxReturnComponent { + message = ''; + + @Output() close = new EventEmitter(); + + get taxReturn(): HeroTaxReturn { + return this.heroTaxReturnService.taxReturn; + } + + @Input() + set taxReturn(htr: HeroTaxReturn) { + this.heroTaxReturnService.taxReturn = htr; + } + + constructor(private heroTaxReturnService: HeroTaxReturnService) {} + + onCanceled() { + this.flashMessage('Canceled'); + this.heroTaxReturnService.restoreTaxReturn(); + } + + onClose() { this.close.emit(); } + + onSaved() { + this.flashMessage('Saved'); + this.heroTaxReturnService.saveTaxReturn(); + } + + flashMessage(msg: string) { + this.message = msg; + setTimeout(() => this.message = '', 500); + } +} + + +The _tax-return-to-edit_ arrives by way of the `@Input()` property, which is implemented with getters and setters. +The setter initializes the component's own instance of the `HeroTaxReturnService` with the incoming return. +The getter always returns what that service says is the current state of the hero. +The component also asks the service to save and restore this tax return. + +This won't work if the service is an application-wide singleton. +Every component would share the same service instance, and each component would overwrite the tax return that belonged to another hero. + +To prevent this, configure the component-level injector of `HeroTaxReturnComponent` to provide the service, using the `providers` property in the component metadata. + + +providers: [HeroTaxReturnService] + + +The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`. +Recall that every component _instance_ has its own injector. +Providing the service at the component level ensures that _every_ instance of the component gets a private instance of the service. This makes sure that no tax return gets overwritten. + +HELPFUL: The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation. + +### Scenario: specialized providers + +Another reason to provide a service again at another level is to substitute a _more specialized_ implementation of that service, deeper in the component tree. + +For example, consider a `Car` component that includes tire service information and depends on other services to provide more details about the car. + +The root injector, marked as (A), uses _generic_ providers for details about `CarService` and `EngineService`. + +1. `Car` component (A). Component (A) displays tire service data about a car and specifies generic services to provide more information about the car. + +2. Child component (B). Component (B) defines its own, _specialized_ providers for `CarService` and `EngineService` that have special capabilities suitable for what's going on in component (B). + +3. Child component (C) as a child of Component (B). Component (C) defines its own, even _more specialized_ provider for `CarService`. + +```mermaid +graph TD; +subgraph COMPONENT_A[Component A] +subgraph COMPONENT_B[Component B] +COMPONENT_C[Component C] +end +end + +style COMPONENT_A fill:#BDD7EE +style COMPONENT_B fill:#FFE699 +style COMPONENT_C fill:#A9D18E,color:#000 +classDef noShadow filter:none +class COMPONENT_A,COMPONENT_B,COMPONENT_C noShadow +``` + +Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself. + +When you resolve an instance of `Car` at the deepest component (C), its injector produces: + +* An instance of `Car` resolved by injector (C) +* An `Engine` resolved by injector (B) +* Its `Tires` resolved by the root injector (A). + +```mermaid +graph BT; + +subgraph A[" "] +direction LR +RootInjector["(A) RootInjector"] +ServicesA["CarService, EngineService, TiresService"] +end + +subgraph B[" "] +direction LR +ParentInjector["(B) ParentInjector"] +ServicesB["CarService2, EngineService2"] +end + +subgraph C[" "] +direction LR +ChildInjector["(C) ChildInjector"] +ServicesC["CarService3"] +end + +direction LR +car["(C) Car"] +engine["(B) Engine"] +tires["(A) Tires"] + +direction BT +car-->ChildInjector +ChildInjector-->ParentInjector-->RootInjector + +class car,engine,tires,RootInjector,ParentInjector,ChildInjector,ServicesA,ServicesB,ServicesC,A,B,C noShadow +style car fill:#A9D18E,color:#000 +style ChildInjector fill:#A9D18E,color:#000 +style engine fill:#FFE699,color:#000 +style ParentInjector fill:#FFE699,color:#000 +style tires fill:#BDD7EE,color:#000 +style RootInjector fill:#BDD7EE,color:#000 +``` + +## More on dependency injection + + + + From d83d16bf32e88501e1a042e6b3935c208c45cc2b Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Sat, 20 Jul 2024 14:16:44 +0900 Subject: [PATCH 2/3] fix: translate hierarchical di guide --- .../di/hierarchical-dependency-injection.md | 668 +++++++++--------- prh.yml | 5 +- 2 files changed, 338 insertions(+), 335 deletions(-) diff --git a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md index 75465edfb4..f06f3c6700 100644 --- a/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md +++ b/adev-ja/src/content/guide/di/hierarchical-dependency-injection.md @@ -1,52 +1,52 @@ -# Hierarchical injectors +## 階局型むンゞェクタヌ -Injectors in Angular have rules that you can leverage to achieve the desired visibility of injectables in your applications. -By understanding these rules, you can determine whether to declare a provider at the application level, in a Component, or in a Directive. +Angularのむンゞェクタヌには、泚入可胜なオブゞェクトのアプリケヌション内での可芖性を思いどおりにするために掻甚できるルヌルがありたす。 +これらのルヌルを理解するこずで、プロバむダヌをアプリケヌションレベル、コンポヌネント内、たたはディレクティブ内で宣蚀する必芁があるかどうかを刀断できたす。 -The applications you build with Angular can become quite large, and one way to manage this complexity is to split up the application into a well-defined tree of components. +Angularで構築するアプリケヌションは非垞に倧きくなる可胜性があり、この耇雑さを管理する1぀の方法は、アプリケヌションを明確に定矩されたコンポヌネントツリヌに分割するこずです。 -There can be sections of your page that work in a completely independent way than the rest of the application, with its own local copies of the services and other dependencies that it needs. -Some of the services that these sections of the application use might be shared with other parts of the application, or with parent components that are further up in the component tree, while other dependencies are meant to be private. +ペヌゞのセクションには、アプリケヌションの残りの郚分ずは完党に独立しお動䜜する郚分があり、そのセクションに必芁なサヌビスやその他の䟝存関係のロヌカルコピヌが持぀こずができたす。 +これらのアプリケヌションセクションが䜿甚するサヌビスの䞀郚は、アプリケヌションの他の郚分やコンポヌネントツリヌの䞊䜍にある芪コンポヌネントず共有される堎合がありたすが、他の䟝存関係はプラむベヌトであるこずを目的ずしおいたす。 -With hierarchical dependency injection, you can isolate sections of the application and give them their own private dependencies not shared with the rest of the application, or have parent components share certain dependencies with its child components only but not with the rest of the component tree, and so on. Hierarchical dependency injection enables you to share dependencies between different parts of the application only when and if you need to. +階局型の䟝存性の泚入を䜿甚するず、アプリケヌションのセクションを分離しおアプリケヌションの残りの郚分ず共有されおいない独自のプラむベヌト䟝存関係を䞎えるか、芪コンポヌネントが特定の䟝存関係を子コンポヌネントのみに共有しおコンポヌネントツリヌの残りの郚分には共有しないようにできたす。階局型の䟝存性の泚入により、必芁な堎合にのみ、アプリケヌションのさたざたな郚分間で䟝存関係を共有できたす。 -## Types of injector hierarchies +## むンゞェクタヌ階局のタむプ -Angular has two injector hierarchies: +Angularには、次の2぀のむンゞェクタヌ階局がありたす。 -| Injector hierarchies | Details | +| むンゞェクタヌ階局 | 詳现 | |:--- |:--- | -| `EnvironmentInjector` hierarchy | Configure an `ElementInjector` in this hierarchy using `@Injectable()` or `providers` array in `ApplicationConfig`. | -| `ElementInjector` hierarchy | Created implicitly at each DOM element. An `ElementInjector` is empty by default unless you configure it in the `providers` property on `@Directive()` or `@Component()`. | +| `EnvironmentInjector` 階局 | `@Injectable()` たたは `ApplicationConfig` の `providers` 配列を䜿甚しお、この階局で `ElementInjector` を構成したす。 | +| `ElementInjector` 階局 | 各 DOM 芁玠で暗黙的に䜜成されたす。 `ElementInjector` は、 `@Directive()` たたは `@Component()` の `providers` プロパティで構成しない限り、デフォルトでは空です。 | - -For `NgModule` based applications, you can provide dependencies with the `ModuleInjector` hierarchy using an `@NgModule()` or `@Injectable()` annotation. + +`NgModule` ベヌスのアプリケヌションの堎合、`@NgModule()` たたは `@Injectable()` アノテヌションを䜿甚しお、`ModuleInjector` 階局で䟝存関係を提䟛できたす。 ### `EnvironmentInjector` -The `EnvironmentInjector` can be configured in one of two ways by using: +`EnvironmentInjector` は、次のいずれかの方法で構成できたす。 -* The `@Injectable()` `providedIn` property to refer to `root` or `platform` -* The `ApplicationConfig` `providers` array +* `@Injectable()` の `providedIn` プロパティを䜿甚しお `root` たたは `platform` を参照する +* `ApplicationConfig` の `providers` 配列を䜿甚する - + -Using the `@Injectable()` `providedIn` property is preferable to using the `ApplicationConfig` `providers` array. With `@Injectable()` `providedIn`, optimization tools can perform tree-shaking, which removes services that your application isn't using. This results in smaller bundle sizes. +`@Injectable()` の `providedIn` プロパティを䜿甚するこずは、 `ApplicationConfig` の `providers` 配列を䜿甚するよりも奜たしいです。 `@Injectable()` の `providedIn` を䜿甚するず、最適化ツヌルはツリヌシェむクを実行しお、アプリケヌションで䜿甚されおいないサヌビスを削陀できたす。これにより、バンドルサむズが小さくなりたす。 -Tree-shaking is especially useful for a library because the application which uses the library may not have a need to inject it. +ツリヌシェむクは、特にラむブラリにずっお有甚です。なぜなら、ラむブラリを䜿甚するアプリケヌションは、ラむブラリを泚入する必芁がない堎合があるからです。 -`EnvironmentInjector` is configured by the `ApplicationConfig.providers`. +`EnvironmentInjector` は、 `ApplicationConfig.providers` によっお構成されたす。 -Provide services using `providedIn` of `@Injectable()` as follows: +`providedIn` を䜿甚しお、次のように `@Injectable()` を䜿甚しおサヌビスを提䟛したす。 import { Injectable } from '@angular/core'; @Injectable({ - providedIn: 'root' // <--provides this service in the root EnvironmentInjector + providedIn: 'root' // <--ルヌト EnvironmentInjector でこのサヌビスを提䟛したす }) export class ItemService { name = 'telephone'; @@ -54,43 +54,43 @@ export class ItemService { -The `@Injectable()` decorator identifies a service class. -The `providedIn` property configures a specific `EnvironmentInjector`, here `root`, which makes the service available in the `root` `EnvironmentInjector`. +`@Injectable()` デコレヌタヌは、サヌビスクラスを識別したす。 +`providedIn` プロパティは、特定の `EnvironmentInjector`ここでは `root`を構成したす。これにより、サヌビスは `root` `EnvironmentInjector` で䜿甚可胜になりたす。 ### ModuleInjector -In the case of `NgModule` based applications, the ModuleInjector can be configured in one of two ways by using: +`NgModule` ベヌスのアプリケヌションの堎合、`ModuleInjector` は、次のいずれかの方法で構成できたす。 -* The `@Injectable()` `providedIn` property to refer to `root` or `platform` -* The `@NgModule()` `providers` array +* `@Injectable()` の `providedIn` プロパティを䜿甚しお `root` たたは `platform` を参照する +* `@NgModule()` の `providers` 配列を䜿甚する -`ModuleInjector` is configured by the `@NgModule.providers` and `NgModule.imports` property. `ModuleInjector` is a flattening of all the providers arrays that can be reached by following the `NgModule.imports` recursively. +`ModuleInjector` は、 `@NgModule.providers` および `NgModule.imports` プロパティによっお構成されたす。 `ModuleInjector` は、 `NgModule.imports` を再垰的にたどるこずによっお到達できるすべおのプロバむダヌ配列をフラット化したものです。 -Child `ModuleInjector` hierarchies are created when lazy loading other `@NgModules`. +子 `ModuleInjector` 階局は、他の `@NgModules` を遅延ロヌドするずきに䜜成されたす。 -### Platform injector +### プラットフォヌムむンゞェクタヌ -There are two more injectors above `root`, an additional `EnvironmentInjector` and `NullInjector()`. +`root` の䞊にさらに2぀のむンゞェクタヌ、远加の `EnvironmentInjector` ず `NullInjector()` がありたす。 -Consider how Angular bootstraps the application with the following in `main.ts`: +Angularが `main.ts` の次の内容でアプリケヌションをブヌトストラップする方法を怜蚎しおください。 bootstrapApplication(AppComponent, appConfig); -The `bootstrapApplication()` method creates a child injector of the platform injector which is configured by the `ApplicationConfig` instance. -This is the `root` `EnvironmentInjector`. +`bootstrapApplication()` メ゜ッドは、 `ApplicationConfig` むンスタンスによっお構成されたプラットフォヌムむンゞェクタヌの子むンゞェクタヌを䜜成したす。 +これが `root` `EnvironmentInjector` です。 -The `platformBrowserDynamic()` method creates an injector configured by a `PlatformModule`, which contains platform-specific dependencies. -This allows multiple applications to share a platform configuration. -For example, a browser has only one URL bar, no matter how many applications you have running. -You can configure additional platform-specific providers at the platform level by supplying `extraProviders` using the `platformBrowser()` function. +`platformBrowserDynamic()` メ゜ッドは、プラットフォヌム固有の䟝存関係を含む `PlatformModule` によっお構成されたむンゞェクタヌを䜜成したす。 +これにより、耇数のアプリケヌションがプラットフォヌム構成を共有できたす。 +たずえば、ブラりザには、実行䞭のアプリケヌションの数にかかわらず、URLバヌは1぀だけです。 +`platformBrowser()` 関数を䜿甚しお `extraProviders` を提䟛するこずにより、プラットフォヌムレベルで远加のプラットフォヌム固有のプロバむダヌを構成できたす。 -The next parent injector in the hierarchy is the `NullInjector()`, which is the top of the tree. -If you've gone so far up the tree that you are looking for a service in the `NullInjector()`, you'll get an error unless you've used `@Optional()` because ultimately, everything ends at the `NullInjector()` and it returns an error or, in the case of `@Optional()`, `null`. -For more information on `@Optional()`, see the [`@Optional()` section](#optional) of this guide. +階局の次の芪むンゞェクタヌは `NullInjector()` で、ツリヌのトップです。 +ツリヌをそこたで䞊に移動しお `NullInjector()` 内でサヌビスを怜玢した堎合、 `@Optional()` を䜿甚しおいない限り、゚ラヌが発生したす。最終的にはすべお `NullInjector()` で終了し、゚ラヌを返すか、 `@Optional()` の堎合、 `null` を返したす。 +`@Optional()` の詳现に぀いおは、このガむドの [`@Optional()` セクション](#optional) を参照しおください。 -The following diagram represents the relationship between the `root` `ModuleInjector` and its parent injectors as the previous paragraphs describe. +次の図は、前の段萜で説明したように、 `root` `ModuleInjector` ずその芪むンゞェクタヌの関係を衚しおいたす。 ```mermaid stateDiagram-v2 @@ -103,17 +103,17 @@ stateDiagram-v2 elementInjector --> nullInjector ``` -While the name `root` is a special alias, other `EnvironmentInjector` hierarchies don't have aliases. -You have the option to create `EnvironmentInjector` hierarchies whenever a dynamically loaded component is created, such as with the Router, which will create child `EnvironmentInjector` hierarchies. +`root` ずいう名前は特別な゚むリアスですが、他の `EnvironmentInjector` 階局にぱむリアスがありたせん。 +動的にロヌドされたコンポヌネントが䜜成されるたびに `EnvironmentInjector` 階局を䜜成するオプションがありたす。たずえば、ルヌタヌを䜿甚するず、子 `EnvironmentInjector` 階局が䜜成されたす。 -All requests forward up to the root injector, whether you configured it with the `ApplicationConfig` instance passed to the `bootstrapApplication()` method, or registered all providers with `root` in their own services. +`ApplicationConfig` むンスタンスを `bootstrapApplication()` メ゜ッドに枡しお構成するか、 `root` で独自のサヌビスにすべおのプロバむダヌを登録したかにかかわらず、すべおの芁求はルヌトむンゞェクタヌに転送されたす。 -If you configure an app-wide provider in the `ApplicationConfig` of `bootstrapApplication`, it overrides one configured for `root` in the `@Injectable()` metadata. -You can do this to configure a non-default provider of a service that is shared with multiple applications. +`bootstrapApplication()` の `ApplicationConfig` でアプリケヌション党䜓のプロバむダヌを構成するず、 `@Injectable()` メタデヌタの `root` で構成されたプロバむダヌがオヌバヌラむドされたす。 +これは、耇数のアプリケヌションで共有されるサヌビスのデフォルト以倖を構成する堎合に行うこずができたす。 -Here is an example of the case where the component router configuration includes a non-default [location strategy](guide/routing#location-strategy) by listing its provider in the `providers` list of the `ApplicationConfig`. +コンポヌネントルヌタヌの構成にデフォルト以倖の [ロケヌション戊略](guide/routing#location-strategy) が含たれおいる堎合、 `ApplicationConfig` の `providers` リストにそのプロバむダヌをリストするこずによっお、その䟋を瀺したす。 ```ts providers: [ @@ -121,16 +121,16 @@ providers: [ ] ``` -For `NgModule` based applications, configure app-wide providers in the `AppModule` `providers`. +`NgModule` ベヌスのアプリケヌションの堎合、アプリケヌション党䜓のプロバむダヌを `AppModule` の `providers` で構成したす。 ### `ElementInjector` -Angular creates `ElementInjector` hierarchies implicitly for each DOM element. +Angularは、各DOM芁玠に察しお `ElementInjector` 階局を暗黙的に䜜成したす。 -Providing a service in the `@Component()` decorator using its `providers` or `viewProviders` property configures an `ElementInjector`. -For example, the following `TestComponent` configures the `ElementInjector` by providing the service as follows: +`@Component()` デコレヌタヌの `providers` たたは `viewProviders` プロパティを䜿甚しおサヌビスを提䟛するず、 `ElementInjector` が構成されたす。 +たずえば、次の `TestComponent` は、次のようにサヌビスを提䟛するこずで `ElementInjector` を構成したす。 @Component({ @@ -140,67 +140,67 @@ For example, the following `TestComponent` configures the `ElementInjector` by p export class TestComponent -HELPFUL: See the [resolution rules](#resolution-rules) section to understand the relationship between the `EnvironmentInjector` tree, the `ModuleInjector` and the `ElementInjector` tree. +HELPFUL: [解決ルヌル](#resolution-rules) セクションを参照しお、 `EnvironmentInjector` ツリヌ、 `ModuleInjector`、および `ElementInjector` ツリヌの関係を理解しおください。 -When you provide services in a component, that service is available by way of the `ElementInjector` at that component instance. -It may also be visible at child component/directives based on visibility rules described in the [resolution rules](#resolution-rules) section. +コンポヌネントでサヌビスを提䟛するず、そのサヌビスは、そのコンポヌネントむンスタンスの `ElementInjector` を介しお䜿甚可胜になりたす。 +[解決ルヌル](#resolution-rules) セクションで説明されおいる可芖性ルヌルに基づいお、子コンポヌネント/ディレクティブでも可芖化される可胜性がありたす。 -When the component instance is destroyed, so is that service instance. +コンポヌネントむンスタンスが砎棄されるず、そのサヌビスむンスタンスも砎棄されたす。 -#### `@Directive()` and `@Component()` +#### `@Directive()` ず `@Component()` -A component is a special type of directive, which means that just as `@Directive()` has a `providers` property, `@Component()` does too. -This means that directives as well as components can configure providers, using the `providers` property. -When you configure a provider for a component or directive using the `providers` property, that provider belongs to the `ElementInjector` of that component or directive. -Components and directives on the same element share an injector. +コンポヌネントは特殊なタむプのディレクティブであるため、 `@Directive()` に `providers` プロパティがあるように、 `@Component()` にも `providers` プロパティがありたす。 +぀たり、ディレクティブずコンポヌネントは、 `providers` プロパティを䜿甚しおプロバむダヌを構成できたす。 +`providers` プロパティを䜿甚しおコンポヌネントたたはディレクティブのプロバむダヌを構成するず、そのプロバむダヌはそのコンポヌネントたたはディレクティブの `ElementInjector` に属したす。 +同じ芁玠䞊のコンポヌネントずディレクティブは、むンゞェクタヌを共有したす。 -## Resolution rules +## 解決ルヌル -When resolving a token for a component/directive, Angular resolves it in two phases: +コンポヌネント/ディレクティブのトヌクンを解決する堎合、Angularは次の2぀のフェヌズで解決したす。 -1. Against its parents in the `ElementInjector` hierarchy. -2. Against its parents in the `EnvironmentInjector` hierarchy. +1. `ElementInjector` 階局の芪に察しお。 +2. `EnvironmentInjector` 階局の芪に察しお。 -When a component declares a dependency, Angular tries to satisfy that dependency with its own `ElementInjector`. -If the component's injector lacks the provider, it passes the request up to its parent component's `ElementInjector`. +コンポヌネントが䟝存関係を宣蚀するず、Angularはその䟝存関係を自身の `ElementInjector` で満たそうずしたす。 +コンポヌネントのむンゞェクタヌにプロバむダヌがない堎合、そのリク゚ストを芪コンポヌネントの `ElementInjector` に枡したす。 -The requests keep forwarding up until Angular finds an injector that can handle the request or runs out of ancestor `ElementInjector` hierarchies. +リク゚ストは、Angularがリク゚ストを凊理できるむンゞェクタヌを芋぀けるか、祖先 `ElementInjector` 階局を䜿い果たすたで、転送され続けたす。 -If Angular doesn't find the provider in any `ElementInjector` hierarchies, it goes back to the element where the request originated and looks in the `EnvironmentInjector` hierarchy. -If Angular still doesn't find the provider, it throws an error. +Angularがいずれの `ElementInjector` 階局でもプロバむダヌを芋぀けられない堎合、リク゚ストが発生した芁玠に戻り、 `EnvironmentInjector` 階局を調べたす。 +それでもAngularがプロバむダヌを芋぀けられない堎合、゚ラヌをスロヌしたす。 -If you have registered a provider for the same DI token at different levels, the first one Angular encounters is the one it uses to resolve the dependency. -If, for example, a provider is registered locally in the component that needs a service, -Angular doesn't look for another provider of the same service. +同じDIトヌクンのプロバむダヌを異なるレベルで登録した堎合、Angularが最初に遭遇するプロバむダヌが、䟝存関係を解決するために䜿甚するプロバむダヌです。 +たずえば、サヌビスを必芁ずするコンポヌネントにプロバむダヌがロヌカルに登録されおいる堎合、 +Angularは同じサヌビスの別のプロバむダヌを探したせん。 -HELPFUL: For `NgModule` based applications, Angular will search the `ModuleInjector` hierarchy if it cannot find a provider in the `ElementInjector` hierarchies. +HELPFUL: `NgModule` ベヌスのアプリケヌションの堎合、Angularは `ElementInjector` 階局でプロバむダヌが芋぀からない堎合、 `ModuleInjector` 階局を怜玢したす。 -## Resolution modifiers +## 解決修食子 -Angular's resolution behavior can be modified with `@Optional()`, `@Self()`, `@SkipSelf()` and `@Host()`. -Import each of them from `@angular/core` and use each in the component class constructor or in the `inject` configuration when you inject your service. +Angularの解決動䜜は、 `@Optional()`ず`@Self()`、`@SkipSelf()`および`@Host()`で倉曎できたす。 +これらのそれぞれを `@angular/core` からむンポヌトし、コンポヌネントクラスコンストラクタヌたたはサヌビスを泚入するずきの `inject` 構成でそれぞれを䜿甚したす。 -### Types of modifiers +### 修食子の皮類 -Resolution modifiers fall into three categories: +解決修食子は、次の3぀のカテゎリヌに分類されたす。 -* What to do if Angular doesn't find what you're looking for, that is `@Optional()` -* Where to start looking, that is `@SkipSelf()` -* Where to stop looking, `@Host()` and `@Self()` +* Angularが探しおいるものが芋぀からない堎合の凊理、぀たり `@Optional()` +* 怜玢を開始する堎所、぀たり `@SkipSelf()` +* 怜玢を停止する堎所、 `@Host()` ず `@Self()` -By default, Angular always starts at the current `Injector` and keeps searching all the way up. -Modifiers allow you to change the starting, or _self_, location and the ending location. +デフォルトでは、Angularは垞に珟圚の `Injector` から始めお、すべおを䞊に怜玢し続けたす。 +修食子を䜿甚するず、開始䜍眮たたは _self_ 䜍眮ず終了䜍眮を倉曎できたす。 -Additionally, you can combine all of the modifiers except: +さらに、次の修食子をすべお組み合わせるこずができたす。 -* `@Host()` and `@Self()` -* `@SkipSelf()` and `@Self()`. +* `@Host()` ず `@Self()` +* `@SkipSelf()` ず `@Self()` ### `@Optional()` -`@Optional()` allows Angular to consider a service you inject to be optional. -This way, if it can't be resolved at runtime, Angular resolves the service as `null`, rather than throwing an error. -In the following example, the service, `OptionalService`, isn't provided in the service, `ApplicationConfig`, `@NgModule()`, or component class, so it isn't available anywhere in the app. +`@Optional()` を䜿甚するず、泚入するサヌビスをオプションずしお扱うこずができたす。 +そのため、実行時に解決できない堎合、Angularはサヌビスを゚ラヌをスロヌするのではなく、 `null` ずしお解決したす。 +次の䟋では、サヌビス `OptionalService` はサヌビス `ApplicationConfig`や`@NgModule()`、コンポヌネントクラスで提䟛されおいないため、アプリケヌションのどこにも䜿甚できたせん。 export class OptionalComponent { @@ -210,12 +210,12 @@ export class OptionalComponent { ### `@Self()` -Use `@Self()` so that Angular will only look at the `ElementInjector` for the current component or directive. +`@Self()` を䜿甚するず、Angularは珟圚のコンポヌネントたたはディレクティブの `ElementInjector` のみを調べたす。 -A good use case for `@Self()` is to inject a service but only if it is available on the current host element. -To avoid errors in this situation, combine `@Self()` with `@Optional()`. +`@Self()` の良いナヌスケヌスは、サヌビスを泚入するこずですが、珟圚のホスト芁玠で䜿甚可胜な堎合のみです。 +この状況で゚ラヌを回避するには、 `@Self()` ず `@Optional()` を組み合わせたす。 -For example, in the following `SelfComponent`, notice the injected `LeafService` in the constructor. +たずえば、次の `SelfComponent` では、コンストラクタヌで泚入された `LeafService` に泚目しおください。 @@ -229,20 +229,20 @@ export class SelfNoDataComponent { } -In this example, there is a parent provider and injecting the service will return the value, however, injecting the service with `@Self()` and `@Optional()` will return `null` because `@Self()` tells the injector to stop searching in the current host element. +この䟋では芪プロバむダヌがあり、サヌビスを泚入するず倀が返されたす。しかし `@Self()` ず `@Optional()` を䜿甚しおサヌビスを泚入するず、 `null` が返されたす。これは、 `@Self()` がむンゞェクタヌに珟圚のホスト芁玠の怜玢を停止するように指瀺するためです。 -Another example shows the component class with a provider for `FlowerService`. -In this case, the injector looks no further than the current `ElementInjector` because it finds the `FlowerService` and returns the tulip 🌷. +別の䟋では、 `FlowerService` のプロバむダヌを備えたコンポヌネントクラスを瀺しおいたす。 +この堎合、むンゞェクタヌは珟圚の `ElementInjector` より先を芋ずに、 `FlowerService` を芋぀けお、チュヌリップ 🌷 を返したす。 ### `@SkipSelf()` -`@SkipSelf()` is the opposite of `@Self()`. -With `@SkipSelf()`, Angular starts its search for a service in the parent `ElementInjector`, rather than in the current one. -So if the parent `ElementInjector` were using the fern 🌿 value for `emoji`, but you had maple leaf 🍁 in the component's `providers` array, Angular would ignore maple leaf 🍁 and use fern 🌿. +`@SkipSelf()` は `@Self()` の逆です。 +`@SkipSelf()` を䜿甚するず、Angular は珟圚のむンゞェクタヌではなく、芪 `ElementInjector` でサヌビスの怜玢を開始したす。 +そのため、芪 `ElementInjector` が `emoji` にシダ 🌿 倀を䜿甚しおいたが、コンポヌネントの `providers` 配列にカ゚デの葉 🍁 が含たれおいる堎合、Angular はカ゚デの葉 🍁 を無芖しお、シダ 🌿 を䜿甚したす。 -To see this in code, assume that the following value for `emoji` is what the parent component were using, as in this service: +これをコヌドで確認するために、芪コンポヌネントが䜿甚する `emoji` の次の倀を想定したす。これは、このサヌビスず同じです。 export class LeafService { @@ -250,8 +250,8 @@ export class LeafService { } -Imagine that in the child component, you had a different value, maple leaf 🍁 but you wanted to use the parent's value instead. -This is when you'd use `@SkipSelf()`: +子コンポヌネントに、異なる倀、カ゚デの葉 🍁 が含たれおいるず想像しおください。ただし、芪の倀を䜿甚したいずしたす。 +これが、 `@SkipSelf()` を䜿甚するタむミングです。 @@ -259,23 +259,23 @@ This is when you'd use `@SkipSelf()`: selector: 'app-skipself', templateUrl: './skipself.component.html', styleUrls: ['./skipself.component.css'], - // Angular would ignore this LeafService instance + // Angular はこの LeafService むンスタンスを無芖したす providers: [{ provide: LeafService, useValue: { emoji: '🍁' } }] }) export class SkipselfComponent { - // Use @SkipSelf() in the constructor + // コンストラクタヌで @SkipSelf() を䜿甚したす constructor(@SkipSelf() public leaf: LeafService) { } } -In this case, the value you'd get for `emoji` would be fern 🌿, not maple leaf 🍁. +この堎合、 `emoji` に察しお取埗する倀は、カ゚デの葉 🍁 ではなく、シダ 🌿 になりたす。 -#### `@SkipSelf()` with `@Optional()` +#### `@SkipSelf()` ず `@Optional()` -Use `@SkipSelf()` with `@Optional()` to prevent an error if the value is `null`. +`@SkipSelf()` ず `@Optional()` を䜿甚するず、倀が `null` の堎合に゚ラヌを防ぐこずができたす。 -In the following example, the `Person` service is injected in the constructor. -`@SkipSelf()` tells Angular to skip the current injector and `@Optional()` will prevent an error should the `Person` service be `null`. +次の䟋では、 `Person` サヌビスがコンストラクタヌで泚入されおいたす。 +`@SkipSelf()` は、Angularに珟圚のむンゞェクタヌをスキップするように指瀺し、 `@Optional()` は `Person` サヌビスが `null` の堎合に゚ラヌを防ぎたす。 class Person { @@ -285,12 +285,12 @@ class Person { ### `@Host()` - + -`@Host()` lets you designate a component as the last stop in the injector tree when searching for providers. +`@Host()` を䜿甚するず、むンゞェクタヌツリヌでプロバむダヌを怜玢する際の終点ずしおコンポヌネントを指定できたす。 -Even if there is a service instance further up the tree, Angular won't continue looking. -Use `@Host()` as follows: +ツリヌの䞊䜍にサヌビスむンスタンスがある堎合でも、Angularは怜玢を続行したせん。 +`@Host()` は次のように䜿甚したす。 @@ -298,24 +298,24 @@ Use `@Host()` as follows: selector: 'app-host', templateUrl: './host.component.html', styleUrls: ['./host.component.css'], - // provide the service + // サヌビスを提䟛したす providers: [{ provide: FlowerService, useValue: { emoji: '🌷' } }] }) export class HostComponent { - // use @Host() in the constructor when injecting the service + // サヌビスを泚入するずきにコンストラクタヌで @Host() を䜿甚したす constructor(@Host() @Optional() public flower?: FlowerService) { } } -Since `HostComponent` has `@Host()` in its constructor, no matter what the parent of `HostComponent` might have as a `flower.emoji` value, the `HostComponent` will use tulip 🌷. +`HostComponent` に `@Host()` があるため、 `HostComponent` の芪が `flower.emoji` 倀ずしお䜕を䜿甚しおいるかに関係なく、 `HostComponent` はチュヌリップ 🌷 を䜿甚したす。 -## Logical structure of the template +## テンプレヌトの論理構造 -When you provide services in the component class, services are visible within the `ElementInjector` tree relative to where and how you provide those services. +コンポヌネントクラスでサヌビスを提䟛する堎合、サヌビスは、サヌビスの提䟛堎所ず方法に応じお、 `ElementInjector` ツリヌ内で可芖になりたす。 -Understanding the underlying logical structure of the Angular template will give you a foundation for configuring services and in turn control their visibility. +Angularテンプレヌトの基になる論理構造を理解するず、サヌビスの構成ず、その可芖性の制埡のための基瀎が埗られたす。 -Components are used in your templates, as in the following example: +コンポヌネントは、次の䟋のようにテンプレヌトで䜿甚されたす。 @@ -323,55 +323,55 @@ Components are used in your templates, as in the following example: -HELPFUL: Usually, you declare the components and their templates in separate files. -For the purposes of understanding how the injection system works, it is useful to look at them from the point of view of a combined logical tree. -The term _logical_ distinguishes it from the render tree, which is your application's DOM tree. -To mark the locations of where the component templates are located, this guide uses the `<#VIEW>` pseudo-element, which doesn't actually exist in the render tree and is present for mental model purposes only. +HELPFUL: 通垞、コンポヌネントずそのテンプレヌトは別々のファむルに宣蚀したす。 +泚入システムの動䜜を理解するために、それらを組み合わせた論理ツリヌの芖点から芋るず䟿利です。 +甚語 _論理_ は、アプリケヌションのDOMツリヌであるレンダリングツリヌず区別しおいたす。 +コンポヌネントテンプレヌトの堎所を瀺すために、このガむドでは `<#VIEW>` 疑䌌芁玠を䜿甚したす。この疑䌌芁玠は、レンダリングツリヌには実際に存圚せず、メンタルモデルの目的でのみ存圚したす。 -The following is an example of how the `` and `` view trees are combined into a single logical tree: +以䞋は、 `` ず `` のビュヌツリヌを1぀の論理ツリヌに結合した䟋です。 <#VIEW> <#VIEW> - 
content goes here
 +  ここにコンテンツが挿入されたす  -Understanding the idea of the `<#VIEW>` demarcation is especially significant when you configure services in the component class. +`<#VIEW>` の区切りの考え方を理解するこずは、特にコンポヌネントクラスでサヌビスを構成する堎合に重芁です。 -## Example: Providing services in `@Component()` +## 䟋 `@Component()` でサヌビスを提䟛する -How you provide services using a `@Component()` (or `@Directive()`) decorator determines their visibility. -The following sections demonstrate `providers` and `viewProviders` along with ways to modify service visibility with `@SkipSelf()` and `@Host()`. +`@Component()`たたは `@Directive()`デコレヌタヌを䜿甚しおサヌビスを提䟛する方法は、サヌビスの可芖性を決めたす。 +次のセクションでは`providers`ず`viewProviders`、`@SkipSelf()`および`@Host()`を䜿甚しおサヌビスの可芖性を倉曎する方法に぀いお説明したす。 -A component class can provide services in two ways: +コンポヌネントクラスでは、次の2぀の方法でサヌビスを提䟛できたす。 -| Arrays | Details | +| 配列 | 詳现 | |:--- |:--- | -| With a `providers` array | `@Component({ providers: [SomeService] })` | -| With a `viewProviders` array | `@Component({ viewProviders: [SomeService] })` | +| `providers` 配列を䜿甚する | `@Component({ providers: [SomeService] })` | +| `viewProviders` 配列を䜿甚する | `@Component({ viewProviders: [SomeService] })` | -In the examples below, you will see the logical tree of an Angular application. -To illustrate how the injector works in the context of templates, the logical tree will represent the HTML structure of the application. -For example, the logical tree will show that `` is a direct children of ``. +次の䟋では、Angularアプリケヌションの論理ツリヌが衚瀺されたす。 +テンプレヌトのコンテキストでむンゞェクタヌがどのように動䜜するかを瀺すために、論理ツリヌはアプリケヌションのHTML構造を衚したす。 +たずえば、論理ツリヌは、 `` が `` の盎接の子であるこずを瀺したす。 -In the logical tree, you will see special attributes: `@Provide`, `@Inject`, and `@ApplicationConfig`. -These aren't real attributes but are here to demonstrate what is going on under the hood. +論理ツリヌでは、 `@Provide` 、 `@Inject` 、および `@ApplicationConfig` ずいう特殊な属性が衚瀺されたす。 +これらは実際の属性ではなく、内郚で䜕が起こっおいるかを説明するためにここにありたす。 -| Angular service attribute | Details | +| Angular サヌビス属性 | 詳现 | |:--- |:--- | -| `@Inject(Token)=>Value` | If `Token` is injected at this location in the logical tree, its value would be `Value`. | -| `@Provide(Token=Value)` | Indicates that `Token` is provided with `Value` at this location in the logical tree. | -| `@ApplicationConfig` | Demonstrates that a fallback `EnvironmentInjector` should be used at this location. | +| `@Inject(Token)=>Value` | 論理ツリヌのこの堎所に `Token` が泚入されおいる堎合、その倀は `Value` になりたす。 | +| `@Provide(Token=Value)` | 論理ツリヌのこの堎所に `Token` が `Value` で提䟛されおいるこずを瀺したす。 | +| `@ApplicationConfig` | この堎所でフォヌルバック `EnvironmentInjector` を䜿甚する必芁があるこずを瀺したす。 | -### Example app structure +### アプリケヌション構造の䟋 -The example application has a `FlowerService` provided in `root` with an `emoji` value of red hibiscus 🌺. +この䟋では、 `emoji` の倀が赀いハむビスカス 🌺 である、 `root` に提䟛される `FlowerService` がありたす。 @Injectable({ @@ -382,24 +382,24 @@ export class FlowerService { } -Consider an application with only an `AppComponent` and a `ChildComponent`. -The most basic rendered view would look like nested HTML elements such as the following: +`AppComponent` ず `ChildComponent` のみが含たれるアプリケヌションを怜蚎しおください。 +最も基本的なレンダリングされたビュヌは、次のようなネストされたHTML芁玠のように芋えたす。 - - + + -However, behind the scenes, Angular uses a logical view representation as follows when resolving injection requests: +ただし、裏偎では、Angularはむンゞェクションリク゚ストを解決するずきに、次のような論理ビュヌ衚珟を䜿甚したす。 - + <#VIEW> - + <#VIEW> @@ -407,12 +407,12 @@ However, behind the scenes, Angular uses a logical view representation as follow -The `<#VIEW>` here represents an instance of a template. -Notice that each component has its own `<#VIEW>`. +ここでの `<#VIEW>` は、テンプレヌトのむンスタンスを衚しおいたす。 +各コンポヌネントには、独自の `<#VIEW>` があるこずに泚意しおください。 -Knowledge of this structure can inform how you provide and inject your services, and give you complete control of service visibility. +この構造を理解するこずで、サヌビスの提䟛方法ず泚入方法を把握し、サヌビスの可芖性を完党に制埡できたす。 -Now, consider that `` injects the `FlowerService`: +次に、 `` が `FlowerService` を泚入しおいるずしたす。 export class AppComponent { @@ -420,19 +420,19 @@ export class AppComponent { } -Add a binding to the `` template to visualize the result: +結果を芖芚化するために、 `` テンプレヌトにバむンディングを远加したす。

Emoji from FlowerService: {{flower.emoji}}

-The output in the view would be: +ビュヌに出力されるのは次のずおりです。 Emoji from FlowerService: 🌺 -In the logical tree, this would be represented as follows: +論理ツリヌでは、これは次のように衚されたす。 -When `` requests the `FlowerService`, it is the injector's job to resolve the `FlowerService` token. -The resolution of the token happens in two phases: +`` が `FlowerService` を芁求するず、むンゞェクタヌは `FlowerService` トヌクンを解決したす。 +トヌクンの解決は次の2぀のフェヌズで行われたす。 -1. The injector determines the starting location in the logical tree and an ending location of the search. - The injector begins with the starting location and looks for the token at each view level in the logical tree. - If the token is found it is returned. +1. むンゞェクタヌは、論理ツリヌ内の開始䜍眮ず怜玢の終了䜍眮を決定したす。 + むンゞェクタヌは開始䜍眮から始めお、論理ツリヌの各ビュヌレベルでトヌクンを怜玢したす。 + トヌクンが芋぀かるず、そのトヌクンが返されたす。 -1. If the token is not found, the injector looks for the closest parent `EnvironmentInjector` to delegate the request to. +1. トヌクンが芋぀からない堎合、むンゞェクタヌはリク゚ストを委任する最も近い芪 `EnvironmentInjector` を怜玢したす。 -In the example case, the constraints are: +この䟋の堎合、制玄は次のずおりです。 -1. Start with `<#VIEW>` belonging to `` and end with ``. +1. `` に属する `<#VIEW>` から始めお、 `` で終了したす。 - * Normally the starting point for search is at the point of injection. - However, in this case `` is a component. `@Component`s are special in that they also include their own `viewProviders`, which is why the search starts at `<#VIEW>` belonging to ``. - This would not be the case for a directive matched at the same location. - * The ending location happens to be the same as the component itself, because it is the topmost component in this application. + * 通垞、怜玢の開始点は泚入ポむントです。 + ただし、この堎合、 `` はコンポヌネントです。 `@Component` は特殊で、独自の `viewProviders` も含たれおいたす。そのため、怜玢は `` に属する `<#VIEW>` から開始されたす。 + これは、同じ堎所に䞀臎するディレクティブでは発生したせん。 + * 終了䜍眮は、コンポヌネント自䜓ず同じになりたす。なぜなら、これはこのアプリケヌションの最䞊䜍コンポヌネントだからです。 -1. The `ElementInjector` provided by the `ApplicationConfig` acts as the fallback injector when the injection token can't be found in the `ElementInjector` hierarchies. +1. `ApplicationConfig` によっお提䟛される `ElementInjector` は、むンゞェクショントヌクンが `ElementInjector` 階局で芋぀からない堎合のフォヌルバックむンゞェクタヌずしお機胜したす。 -### Using the `providers` array +### `providers` 配列を䜿甚する -Now, in the `ChildComponent` class, add a provider for `FlowerService` to demonstrate more complex resolution rules in the upcoming sections: +次に、 `ChildComponent` クラスで、今埌のセクションでより耇雑な解決ルヌルを説明するために、 `FlowerService` のプロバむダヌを远加したす。 @@ -478,32 +478,32 @@ Now, in the `ChildComponent` class, add a provider for `FlowerService` to demons selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'], - // use the providers array to provide a service + // プロバむダヌ配列を䜿甚しおサヌビスを提䟛したす providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }] }) export class ChildComponent { - // inject the service + // サヌビスを泚入したす constructor( public flower: FlowerService) { } } -Now that the `FlowerService` is provided in the `@Component()` decorator, when the `` requests the service, the injector has only to look as far as the `ElementInjector` in the ``. -It won't have to continue the search any further through the injector tree. +`FlowerService` が `@Component()` デコレヌタヌで提䟛されるようになったため、 `` がサヌビスを芁求するず、むンゞェクタヌは `` の `ElementInjector` ほど遠くたでしか芋なくおもよくなりたす。 +むンゞェクタヌは、むンゞェクタヌツリヌをさらに怜玢する必芁はありたせん。 -The next step is to add a binding to the `ChildComponent` template. +次のステップは、 `ChildComponent` テンプレヌトにバむンディングを远加するこずです。

Emoji from FlowerService: {{flower.emoji}}

-To render the new values, add `` to the bottom of the `AppComponent` template so the view also displays the sunflower: +新しい倀をレンダリングするために、ビュヌにひたわりも衚瀺されるように、 `AppComponent` テンプレヌトの䞋郚に `` を远加したす。 Child Component Emoji from FlowerService: 🌻 -In the logical tree, this is represented as follows: +論理ツリヌでは、これは次のように衚されたす。 @@ -512,8 +512,8 @@ In the logical tree, this is represented as follows: <#VIEW>

Emoji from FlowerService: {{flower.emoji}} (🌺)

"🌻"> - <#VIEW> + @Inject(FlowerService)=>"🌻"> + <#VIEW>

Child Component

Emoji from FlowerService: {{flower.emoji}} (🌻)

@@ -523,23 +523,23 @@ In the logical tree, this is represented as follows:
-When `` requests the `FlowerService`, the injector begins its search at the `<#VIEW>` belonging to `` \(`<#VIEW>` is included because it is injected from `@Component()`\) and ends with ``. -In this case, the `FlowerService` is resolved in the `providers` array with sunflower 🌻 of the ``. -The injector doesn't have to look any further in the injector tree. -It stops as soon as it finds the `FlowerService` and never sees the red hibiscus 🌺. +`` が `FlowerService` を芁求するず、むンゞェクタヌは `` に属する `<#VIEW>``@Component()` から泚入されるため `<#VIEW>` が含たれおいたすから始めお、 `` で終了したす。 +この堎合、 `FlowerService` は、 `` の `providers` 配列で、ひたわり 🌻 を䜿甚しお解決されたす。 +むンゞェクタヌは、むンゞェクタヌツリヌをさらに怜玢する必芁はありたせん。 +`FlowerService` を芋぀けるずすぐに停止し、赀いハむビスカス 🌺 は芋えたせん。 -### Using the `viewProviders` array +### `viewProviders` 配列を䜿甚する -Use the `viewProviders` array as another way to provide services in the `@Component()` decorator. -Using `viewProviders` makes services visible in the `<#VIEW>`. +`viewProviders` 配列は、 `@Component()` デコレヌタヌでサヌビスを提䟛する別の方法です。 +`viewProviders` を䜿甚するず、サヌビスは `<#VIEW>` で可芖になりたす。 -HELPFUL: The steps are the same as using the `providers` array, with the exception of using the `viewProviders` array instead. +HELPFUL: ステップは `providers` 配列を䜿甚する堎合ず同じですが、 `viewProviders` 配列を䜿甚する点が異なりたす。 -For step-by-step instructions, continue with this section. -If you can set it up on your own, skip ahead to [Modifying service availability](#visibility-of-provided-tokens). +ステップバむステップの手順に぀いおは、このセクションを続行しおください。 +自分で蚭定できる堎合は、[サヌビスの可甚性を倉曎する](#visibility-of-provided-tokens) に進んでください。 -For demonstration, we are building an `AnimalService` to demonstrate `viewProviders`. -First, create an `AnimalService` with an `emoji` property of whale 🐳: +デモのために、 `AnimalService` を䜜成しお、 `viewProviders` を瀺したす。 +最初に、 `emoji` プロパティがクゞラ 🐳 である `AnimalService` を䜜成したす。 import { Injectable } from '@angular/core'; @@ -552,7 +552,7 @@ export class AnimalService { } -Following the same pattern as with the `FlowerService`, inject the `AnimalService` in the `AppComponent` class: +`FlowerService` ず同じパタヌンに埓っお、 `AppComponent` クラスに `AnimalService` を泚入したす。 export class AppComponent { @@ -562,10 +562,10 @@ export class AppComponent { } -HELPFUL: You can leave all the `FlowerService` related code in place as it will allow a comparison with the `AnimalService`. +HELPFUL: `FlowerService` に関連するコヌドはすべおそのたたにしおおくこずができたす。これにより、 `AnimalService` ずの比范が可胜になりたす。 -Add a `viewProviders` array and inject the `AnimalService` in the `` class, too, but give `emoji` a different value. -Here, it has a value of dog 🐶. +`viewProviders` 配列を远加し、 `` クラスにも `AnimalService` を泚入したすが、 `emoji` に異なる倀を䞎えたす。 +ここでは、犬 🐶 の倀がありたす。 @@ -573,31 +573,31 @@ Here, it has a value of dog 🐶. selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'], - // provide services + // サヌビスを提䟛したす providers: [{ provide: FlowerService, useValue: { emoji: '🌻' } }], viewProviders: [{ provide: AnimalService, useValue: { emoji: '🐶' } }] }) export class ChildComponent { - // inject service + // サヌビスを泚入したす constructor( public flower: FlowerService, public animal: AnimalService) { } ... } -Add bindings to the `ChildComponent` and the `AppComponent` templates. -In the `ChildComponent` template, add the following binding: +`ChildComponent` ず `AppComponent` のテンプレヌトにバむンディングを远加したす。 +`ChildComponent` テンプレヌトに、次のバむンディングを远加したす。

Emoji from AnimalService: {{animal.emoji}}

-Additionally, add the same to the `AppComponent` template: +さらに、 `AppComponent` テンプレヌトにも同じものを远加したす。

Emoji from AnimalService: {{animal.emoji}}

s
-Now you should see both values in the browser: +これで、ブラりザに䞡方の倀が衚瀺されたす。 @@ -609,7 +609,7 @@ Emoji from AnimalService: 🐶 -The logic tree for this example of `viewProviders` is as follows: +この `viewProviders` の䟋の論理ツリヌは次のずおりです。 @@ -619,7 +619,7 @@ The logic tree for this example of `viewProviders` is as follows: <#VIEW @Provide(AnimalService="🐶") @Inject(AnimalService=>"🐶")> - +

Emoji from AnimalService: {{animal.emoji}} (🐶)

@@ -628,18 +628,18 @@ The logic tree for this example of `viewProviders` is as follows:
-Just as with the `FlowerService` example, the `AnimalService` is provided in the `` `@Component()` decorator. -This means that since the injector first looks in the `ElementInjector` of the component, it finds the `AnimalService` value of dog 🐶. -It doesn't need to continue searching the `ElementInjector` tree, nor does it need to search the `ModuleInjector`. +`FlowerService` の䟋ず同様に、 `AnimalService` は `` の `@Component()` デコレヌタヌで提䟛されおいたす。 +぀たり、むンゞェクタヌは最初にコンポヌネントの `ElementInjector` を調べるため、犬 🐶 の `AnimalService` 倀が芋぀かりたす。 +むンゞェクタヌは、 `ElementInjector` ツリヌをさらに怜玢する必芁も、 `ModuleInjector` を怜玢する必芁もありたせん。 -### `providers` vs. `viewProviders` +### `providers` ず `viewProviders` の違い -The `viewProviders` field is conceptually similar to `providers`, but there is one notable difference. -Configured providers in `viewProviders` are not visible to projected content that ends up as a logical children of the component. +`viewProviders` フィヌルドは、抂念的には `providers` ず䌌おいたすが、1぀の顕著な違いがありたす。 +`viewProviders` で構成されたプロバむダヌは、コンポヌネントの論理的な子になる投圱されたコンテンツには可芖ではありたせん。 -To see the difference between using `providers` and `viewProviders`, add another component to the example and call it `InspectorComponent`. -`InspectorComponent` will be a child of the `ChildComponent`. -In `inspector.component.ts`, inject the `FlowerService` and `AnimalService` in the constructor: +`providers` ず `viewProviders` の違いを確認するために、別のコンポヌネントを䟋に远加しお、 `InspectorComponent` ず呌びたす。 +`InspectorComponent` は、 `ChildComponent` の子になりたす。 +`inspector.component.ts` で、コンストラクタヌに `FlowerService` ず `AnimalService` を泚入したす。 export class InspectorComponent { @@ -647,15 +647,15 @@ export class InspectorComponent { } -You do not need a `providers` or `viewProviders` array. -Next, in `inspector.component.html`, add the same markup from previous components: +`providers` たたは `viewProviders` 配列は必芁ありたせん。 +次に、 `inspector.component.html` に、以前のコンポヌネントず同じマヌクアップを远加したす。

Emoji from FlowerService: {{flower.emoji}}

Emoji from AnimalService: {{animal.emoji}}

-Remember to add the `InspectorComponent` to the `ChildComponent` `imports` array. +`InspectorComponent` を `ChildComponent` の `imports` 配列に远加するこずを忘れないでください。 @@ -666,7 +666,7 @@ Remember to add the `InspectorComponent` to the `ChildComponent` `imports` array -Next, add the following to `child.component.html`: +次に、 `child.component.html` に次を远加したす。 @@ -681,9 +681,9 @@ Next, add the following to `child.component.html`: -`` allows you to project content, and `` inside the `ChildComponent` template makes the `InspectorComponent` a child component of `ChildComponent`. +`` を䜿甚するずコンテンツを投圱でき、 `ChildComponent` テンプレヌト内の `` は、 `InspectorComponent` を `ChildComponent` の子コンポヌネントにしたす。 -Next, add the following to `app.component.html` to take advantage of content projection. +次に、コンテンツ投圱を掻甚するために、 `app.component.html` に次を远加したす。 @@ -691,7 +691,7 @@ Next, add the following to `app.component.html` to take advantage of content pro -The browser now renders the following, omitting the previous examples for brevity: +これで、ブラりザには、以前の䟋は省略しお、次のものがレンダリングされたす。 ... @@ -705,13 +705,13 @@ Emoji from AnimalService: 🐶 -These four bindings demonstrate the difference between `providers` and `viewProviders`. -Remember that the dog emoji 🐶 is declared inside the `<#VIEW>` of `ChildComponent` and isn't visible to the projected content. -Instead, the projected content sees the whale 🐳. +これらの4぀のバむンディングは、 `providers` ず `viewProviders` の違いを瀺しおいたす。 +犬の絵文字 🐶 は、 `ChildComponent` の `<#VIEW>` 内に宣蚀され、投圱されたコンテンツには可芖ではないこずを芚えおおいおください。 +代わりに、投圱されたコンテンツには、クゞラ 🐳 が衚瀺されたす。 -However, in the next output section though, the `InspectorComponent` is an actual child component of `ChildComponent`, `InspectorComponent` is inside the `<#VIEW>`, so when it asks for the `AnimalService`, it sees the dog 🐶. +ただし、次の出力セクションでは `InspectorComponent` は `ChildComponent` の実際の子コンポヌネントです。そしお `InspectorComponent` は `<#VIEW>` の内偎にあるため、 `AnimalService` を芁求するず、犬 🐶 が衚瀺されたす。 -The `AnimalService` in the logical tree would look like this: +論理ツリヌ内の `AnimalService` は、次のようになりたす。 @@ -721,7 +721,7 @@ The `AnimalService` in the logical tree would look like this: <#VIEW @Provide(AnimalService="🐶") @Inject(AnimalService=>"🐶")> - +

Emoji from AnimalService: {{animal.emoji}} (🐶)

@@ -743,25 +743,25 @@ The `AnimalService` in the logical tree would look like this: -The projected content of `` sees the whale 🐳, not the dog 🐶, because the dog 🐶 is inside the `` `<#VIEW>`. -The `` can only see the dog 🐶 if it is also within the `<#VIEW>`. +`` の投圱されたコンテンツには、クゞラ 🐳 が衚瀺され、犬 🐶 は衚瀺されたせん。これは、犬 🐶 が `` の `<#VIEW>` の内偎にあるためです。 +`` は、 `<#VIEW>` の内偎にある堎合にのみ、犬 🐶 を衚瀺できたす。 -### Visibility of provided tokens +### 提䟛されたトヌクンの可芖性 -Visibility decorators influence where the search for the injection token begins and ends in the logic tree. -To do this, place visibility decorators at the point of injection, that is, the `constructor()`, rather than at a point of declaration. +可芖性デコレヌタヌは、論理ツリヌ内でむンゞェクショントヌクンの怜玢を開始する堎所ず終了する堎所を制埡したす。 +これを行うには、可芖性デコレヌタヌを泚入ポむント、぀たり `constructor()` に配眮し、宣蚀ポむントに配眮しないでください。 -To alter where the injector starts looking for `FlowerService`, add `@SkipSelf()` to the `` `@Inject` declaration where `FlowerService` is injected. -This declaration is in the `` constructor as shown in `child.component.ts`: +むンゞェクタヌが `FlowerService` の怜玢を開始する堎所を倉曎するには、 `` の `@Inject` 宣蚀に `@SkipSelf()` を远加したす。 +この宣蚀は、 `child.component.ts` に瀺すように、 `` のコンストラクタヌにありたす。 constructor(@SkipSelf() public flower: FlowerService) { } -With `@SkipSelf()`, the `` injector doesn't look to itself for the `FlowerService`. -Instead, the injector starts looking for the `FlowerService` at the `ElementInjector` of the ``, where it finds nothing. -Then, it goes back to the `` `ModuleInjector` and finds the red hibiscus 🌺 value, which is available because `` and `` share the same `ModuleInjector`. -The UI renders the following: +`@SkipSelf()` を䜿甚するず、 `` むンゞェクタヌは、 `FlowerService` を自身で怜玢したせん。 +代わりに、むンゞェクタヌは `` の `ElementInjector` で `FlowerService` の怜玢を開始し、䜕も芋぀かりたせん。 +次に、 `` の `ModuleInjector` に戻り、 `` ず `` が同じ `ModuleInjector` を共有しおいるため、赀いハむビスカス 🌺 倀が芋぀かりたす。 +UIには次のように衚瀺されたす。 @@ -769,7 +769,7 @@ Emoji from FlowerService: 🌺 -In a logical tree, this same idea might look like this: +論理ツリヌでは、この同じ考え方は次のようになりたす。 @@ -778,7 +778,7 @@ In a logical tree, this same idea might look like this: <#VIEW> <#VIEW @Inject(FlowerService, SkipSelf)=>"🌺"> - + @@ -786,18 +786,18 @@ In a logical tree, this same idea might look like this: -Though `` provides the sunflower 🌻, the application renders the red hibiscus 🌺 because `@SkipSelf()` causes the current injector (`app-child`) to skip itself and look to its parent. +`` はひたわり 🌻 を提䟛したすが、アプリケヌションは赀いハむビスカス 🌺 をレンダリングしたす。これは、 `@SkipSelf()` によっお珟圚のむンゞェクタヌ`app-child`が自身をスキップしお芪を調べるためです。 -If you now add `@Host()` (in addition to the `@SkipSelf()`), the result will be `null`. -This is because `@Host()` limits the upper bound of the search to the `app-child` `<#VIEW>`. -Here's the idea in the logical tree: +`@Host()` を远加するず`@SkipSelf()` に加えお、結果は `null` になりたす。 +これは、 `@Host()` が怜玢の䞊限を `` の `<#VIEW>` に制限するためです。 +論理ツリヌでの考え方は次のずおりです。 "🌺"> - <#VIEW> - + <#VIEW> + <#VIEW @Inject(FlowerService, @SkipSelf, @Host, @Optional)=>null> @@ -806,15 +806,15 @@ Here's the idea in the logical tree: -Here, the services and their values are the same, but `@Host()` stops the injector from looking any further than the `<#VIEW>` for `FlowerService`, so it doesn't find it and returns `null`. +ここではサヌビスずその倀は同じですが、 `@Host()` によっおむンゞェクタヌは `<#VIEW>` より先を `FlowerService` に぀いお怜玢できなくなるため、芋぀からずに `null` を返したす。 -### `@SkipSelf()` and `viewProviders` +### `@SkipSelf()` ず `viewProviders` -Remember, `` provides the `AnimalService` in the `viewProviders` array with the value of dog 🐶. -Because the injector has only to look at the `ElementInjector` of the `` for the `AnimalService`, it never sees the whale 🐳. +芚えおおいおください。 `` は、 `viewProviders` 配列で `AnimalService` を提䟛し、その倀は犬 🐶 です。 +むンゞェクタヌは、 `` の `ElementInjector` を `AnimalService` に぀いお調べるだけなので、クゞラ 🐳 は芋えたせん。 -As in the `FlowerService` example, if you add `@SkipSelf()` to the constructor for the `AnimalService`, the injector won't look in the `ElementInjector` of the current `` for the `AnimalService`. -Instead, the injector will begin at the `` `ElementInjector`. +`FlowerService` の䟋ず同様に、コンストラクタヌに `@SkipSelf()` を远加するず、むンゞェクタヌは珟圚の `` の `ElementInjector` を `AnimalService` に぀いお怜玢したせん。 +代わりに、むンゞェクタヌは `` の `ElementInjector` で怜玢を開始したす。 @Component({ @@ -827,17 +827,17 @@ Instead, the injector will begin at the `` `ElementInjector`. }) -The logical tree looks like this with `@SkipSelf()` in ``: +論理ツリヌは、 `` に `@SkipSelf()` がある堎合、次のようになりたす。 "🐳")> - <#VIEW> + <#VIEW> <#VIEW @Provide(AnimalService="🐶") @Inject(AnimalService, SkipSelf=>"🐳")> - + @@ -845,13 +845,13 @@ The logical tree looks like this with `@SkipSelf()` in ``: -With `@SkipSelf()` in the ``, the injector begins its search for the `AnimalService` in the `` `ElementInjector` and finds whale 🐳. +`` に `@SkipSelf()` があるず、むンゞェクタヌは `` の `ElementInjector` で `AnimalService` の怜玢を開始し、クゞラ 🐳 を芋぀けたす。 -### `@Host()` and `viewProviders` +### `@Host()` ず `viewProviders` -If you just use `@Host()` for the injection of `AnimalService`, the result is dog 🐶 because the injector finds the `AnimalService` in the `` `<#VIEW>` itself. -The `ChildComponent` configures the `viewProviders` so that the dog emoji is provided as `AnimalService` value. -You can also see `@Host()` in the constructor: +`@Host()` を単独で䜿甚した堎合、結果は犬 🐶 になりたす。なぜなら、むンゞェクタヌは `` の `<#VIEW>` 自䜓で `AnimalService` を芋぀けるためです。 +`ChildComponent` は、 `viewProviders` を構成しお、犬の絵文字が `AnimalService` 倀ずしお提䟛されるようにしたす。 +たた、コンストラクタヌに `@Host()` があるこずもわかりたす。 @Component({ @@ -867,7 +867,7 @@ export class ChildComponent { } -`@Host()` causes the injector to look until it encounters the edge of the `<#VIEW>`. +`@Host()` によっお、むンゞェクタヌは `<#VIEW>` の端に出䌚うたで怜玢したす。 @@ -876,7 +876,7 @@ export class ChildComponent { <#VIEW> <#VIEW @Provide(AnimalService="🐶") - @Inject(AnimalService, @Host=>"🐶")> + @Inject(AnimalService, @Host=>"🐶")> @@ -884,7 +884,7 @@ export class ChildComponent { -Add a `viewProviders` array with a third animal, hedgehog 🦔, to the `app.component.ts` `@Component()` metadata: +3番目の動物、ハリネズミ 🦔 を含む `viewProviders` 配列を、 `app.component.ts` の `@Component()` メタデヌタに远加したす。 @Component({ @@ -899,8 +899,8 @@ Add a `viewProviders` array with a third animal, hedgehog 🦔 -Next, add `@SkipSelf()` along with `@Host()` to the constructor for the `AnimalService` injection in `child.component.ts`. -Here are `@Host()` and `@SkipSelf()` in the `` constructor: +次に、 `child.component.ts` で `AnimalService` の泚入のコンストラクタヌに `@SkipSelf()` ず `@Host()` を远加したす。 +以䞋は、 `` のコンストラクタヌにある `@Host()` ず `@SkipSelf()` です。 export class ChildComponent { @@ -911,16 +911,16 @@ export class ChildComponent { - + -When `@Host()` and `@SkipSelf()` were applied to the `FlowerService`, which is in the `providers` array, the result was `null` because `@SkipSelf()` starts its search in the `` injector, but `@Host()` stops searching at `<#VIEW>` —where there is no `FlowerService` -In the logical tree, you can see that the `FlowerService` is visible in ``, not its `<#VIEW>`. +`@Host()` ず `@SkipSelf()` が `providers` 配列にある `FlowerService` に適甚された堎合、結果は `null` になりたした。これは、 `@SkipSelf()` が `` むンゞェクタヌで怜玢を開始したすが、 `@Host()` は `<#VIEW>` での怜玢を停止するためです。そこには `FlowerService` はありたせん。 +論理ツリヌでは、 `FlowerService` は `` で可芖であり、 `<#VIEW>` では可芖ではないこずがわかりたす。 -However, the `AnimalService`, which is provided in the `AppComponent` `viewProviders` array, is visible. +ただし、 `AppComponent` の `viewProviders` 配列で提䟛されおいる `AnimalService` は可芖です。 -The logical tree representation shows why this is: +論理ツリヌの衚珟は、これが理由を瀺しおいたす。 @@ -928,11 +928,11 @@ The logical tree representation shows why this is: @Inject(AnimalService=>"🐳")> <#VIEW @Provide(AnimalService="🦔") @Inject(AnimalService, @Optional)=>"🦔"> - + <#VIEW @Provide(AnimalService="🐶") @Inject(AnimalService, @SkipSelf, @Host, @Optional)=>"🦔"> - + @@ -940,23 +940,23 @@ The logical tree representation shows why this is: -`@SkipSelf()`, causes the injector to start its search for the `AnimalService` at the ``, not the ``, where the request originates, and `@Host()` stops the search at the `` `<#VIEW>`. -Since `AnimalService` is provided by way of the `viewProviders` array, the injector finds hedgehog 🦔 in the `<#VIEW>`. +`@SkipSelf()` は、むンゞェクタヌが `AnimalService` の怜玢を芁求が発生した `` ではなく、 `` で開始するように指瀺し、 `@Host()` は `` の `<#VIEW>` で怜玢を停止したす。 +`AnimalService` は `viewProviders` 配列を介しお提䟛されるため、むンゞェクタヌは `<#VIEW>` でハリネズミ 🦔 を芋぀けたす。 -## Example: `ElementInjector` use cases +## 䟋 `ElementInjector` のナヌスケヌス -The ability to configure one or more providers at different levels opens up useful possibilities. +さたざたなレベルで1぀以䞊のプロバむダヌを構成する機胜により、䟿利な可胜性が開かれたす。 -### Scenario: service isolation +### シナリオサヌビスの分離 -Architectural reasons may lead you to restrict access to a service to the application domain where it belongs. -For example, consider we build a `VillainsListComponent` that displays a list of villains. -It gets those villains from a `VillainsService`. +アヌキテクチャ䞊の理由から、サヌビスぞのアクセスを属するアプリケヌションドメむンに制限する必芁がある堎合がありたす。 +たずえば、悪圹のリストを衚瀺する `VillainsListComponent` を構築するずしたす。 +この悪圹は、 `VillainsService` から取埗されたす。 -If you provide `VillainsService` in the root `AppModule`, it will make `VillainsService` visible everywhere in the application. -If you later modify the `VillainsService`, you could break something in other components that started depending this service by accident. +`VillainsService` をルヌトの `AppModule` で提䟛するず、 `VillainsService` がアプリケヌションのすべおの堎所で可芖になりたす。 +埌で `VillainsService` を倉曎した堎合、誀っおこのサヌビスに䟝存し始めた他のコンポヌネントで䜕かが壊れる可胜性がありたす。 -Instead, you should provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this: +代わりに、次のように `VillainsListComponent` の `providers` メタデヌタで `VillainsService` を提䟛する必芁がありたす。 @@ -968,34 +968,34 @@ Instead, you should provide the `VillainsService` in the `providers` metadata of export class VillainsListComponent {} -By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else, the service becomes available only in the `VillainsListComponent` and its subcomponent tree. +`VillainsService` を `VillainsListComponent` メタデヌタで提䟛し、他の堎所では提䟛しないず、サヌビスは `VillainsListComponent` ずそのサブコンポヌネントツリヌのみに䜿甚可胜になりたす。 -`VillainService` is a singleton with respect to `VillainsListComponent` because that is where it is declared. -As long as `VillainsListComponent` does not get destroyed it will be the same instance of `VillainService` but if there are multiple instances of `VillainsListComponent`, then each instance of `VillainsListComponent` will have its own instance of `VillainService`. +`VillainService` は、 `VillainsListComponent` に察しおシングルトンです。なぜなら、それが宣蚀されおいる堎所だからです。 +`VillainsListComponent` が砎棄されない限り `VillainService` のむンスタンスは同じです。ただし `VillainsListComponent` のむンスタンスが耇数ある堎合、 `VillainsListComponent` の各むンスタンスには、独自の `VillainService` むンスタンスが1぀ず぀ありたす。 -### Scenario: multiple edit sessions +### シナリオ耇数の線集セッション -Many applications allow users to work on several open tasks at the same time. -For example, in a tax preparation application, the preparer could be working on several tax returns, switching from one to the other throughout the day. +倚くのアプリケヌションでは、ナヌザヌは同時に耇数のオヌプンタスクで䜜業できたす。 +たずえば、皎務申告の䜜成アプリケヌションでは、䜜成者は耇数の皎務申告で䜜業し、1日を通しおそれらを切り替えるこずができたす。 -To demonstrate that scenario, imagine a `HeroListComponent` that displays a list of super heroes. +そのシナリオを瀺すために、スヌパヌヒヌロヌのリストを衚瀺する `HeroListComponent` を考えおみおください。 -To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return. -Each selected hero tax return opens in its own component and multiple returns can be open at the same time. +ヒヌロヌの皎務申告を開くために、䜜成者はヒヌロヌの名前をクリックするず、その申告を線集するためのコンポヌネントが開きたす。 +遞択したヒヌロヌの皎務申告は、それぞれ独自のコンポヌネントで開き、耇数の申告を同時に開くこずができたす。 -Each tax return component has the following characteristics: +各皎務申告コンポヌネントには、次の機胜がありたす。 -* Is its own tax return editing session -* Can change a tax return without affecting a return in another component -* Has the ability to save the changes to its tax return or cancel them +* 独自の皎務申告の線集セッションを持ちたす +* 別のコンポヌネントの申告に圱響を䞎えずに皎務申告を倉曎できたす +* 皎務申告の倉曎を保存するか、キャンセルする機胜がありたす -Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes. -That would be a straightforward task for a hero tax return. -In the real world, with a rich tax return data model, the change management would be tricky. -You could delegate that management to a helper service, as this example does. +`HeroTaxReturnComponent` に、倉曎を管理および埩元するためのロゞックがあるずしたす。 +これは、ヒヌロヌの皎務申告にずっおは簡単なタスクです。 +珟実䞖界では、豊富な皎務申告デヌタモデルでは、倉曎管理が耇雑になりたす。 +この䟋のように、この管理をヘルパヌサヌビスに委任できたす。 -The `HeroTaxReturnService` caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it. -It also delegates to the application-wide singleton `HeroService`, which it gets by injection. +`HeroTaxReturnService` は、単䞀の `HeroTaxReturn` をキャッシュし、その申告ぞの倉曎を远跡し、保存たたは埩元できたす。 +たた、泚入によっお取埗したアプリケヌション党䜓のシングルトン `HeroService` に委任したす。 import { Injectable } from '@angular/core'; @@ -1029,7 +1029,7 @@ export class HeroTaxReturnService { } -Here is the `HeroTaxReturnComponent` that makes use of `HeroTaxReturnService`. +以䞋は、 `HeroTaxReturnService` を䜿甚する `HeroTaxReturnComponent` です。 import { Component, EventEmitter, Input, Output } from '@angular/core'; @@ -1077,39 +1077,39 @@ export class HeroTaxReturnComponent { } -The _tax-return-to-edit_ arrives by way of the `@Input()` property, which is implemented with getters and setters. -The setter initializes the component's own instance of the `HeroTaxReturnService` with the incoming return. -The getter always returns what that service says is the current state of the hero. -The component also asks the service to save and restore this tax return. +_線集察象の皎務申告_ は、 `@Input()` プロパティを介しお到着したす。これは、ゲッタヌずセッタヌで実装されおいたす。 +セッタヌは、コンポヌネント自身の `HeroTaxReturnService` むンスタンスを、受信した申告で初期化したす。 +ゲッタヌは垞に、そのサヌビスがヒヌロヌの珟圚の状態であるず刀断したものを返したす。 +コンポヌネントは、この皎務申告を保存および埩元するこずもサヌビスに芁求したす。 -This won't work if the service is an application-wide singleton. -Every component would share the same service instance, and each component would overwrite the tax return that belonged to another hero. +これは、サヌビスがアプリケヌション党䜓のシングルトンである堎合に機胜したせん。 +すべおのコンポヌネントは同じサヌビスむンスタンスを共有し、各コンポヌネントは別のヒヌロヌに属する皎務申告を䞊曞きしたす。 -To prevent this, configure the component-level injector of `HeroTaxReturnComponent` to provide the service, using the `providers` property in the component metadata. +これを防ぐために、コンポヌネントレベルのむンゞェクタヌ `HeroTaxReturnComponent` を構成しお、コンポヌネントメタデヌタの `providers` プロパティを䜿甚しおサヌビスを提䟛したす。 providers: [HeroTaxReturnService] -The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`. -Recall that every component _instance_ has its own injector. -Providing the service at the component level ensures that _every_ instance of the component gets a private instance of the service. This makes sure that no tax return gets overwritten. +`HeroTaxReturnComponent` には、 `HeroTaxReturnService` の独自の提䟛者がいたす。 +芚えおおいおください。すべおのコンポヌネントの _むンスタンス_ には、独自のむンゞェクタヌがありたす。 +コンポヌネントレベルでサヌビスを提䟛するず、コンポヌネントの _すべおの_ むンスタンスは、サヌビスのプラむベヌトむンスタンスを1぀ず぀取埗するこずが保蚌されたす。これにより、皎務申告が䞊曞きされないようにしたす。 -HELPFUL: The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation. +HELPFUL: シナリオコヌドの残りは、ドキュメントの他の堎所で孊習できる他のAngular機胜ずテクニックに䟝存しおいたす。 -### Scenario: specialized providers +### シナリオ特殊なプロバむダヌ -Another reason to provide a service again at another level is to substitute a _more specialized_ implementation of that service, deeper in the component tree. +別のレベルでサヌビスを再床提䟛するもう1぀の理由は、コンポヌネントツリヌのさらに深い堎所で、そのサヌビスの _より特殊な_ 実装を眮き換えるためです。 -For example, consider a `Car` component that includes tire service information and depends on other services to provide more details about the car. +たずえば、タむダサヌビスの情報を含み、他のサヌビスに䟝存しお車の詳现情報を提䟛する `Car` コンポヌネントを怜蚎しおください。 -The root injector, marked as (A), uses _generic_ providers for details about `CarService` and `EngineService`. +ルヌトむンゞェクタヌ(A) ずマヌク付けは、 `CarService` ず `EngineService` に぀いお、_汎甚的な_ プロバむダヌを䜿甚したす。 -1. `Car` component (A). Component (A) displays tire service data about a car and specifies generic services to provide more information about the car. +1. `Car` コンポヌネント (A)。コンポヌネント (A) は、車のタむダサヌビスデヌタを衚瀺し、車の詳现情報を提䟛するための汎甚サヌビスを指定したす。 -2. Child component (B). Component (B) defines its own, _specialized_ providers for `CarService` and `EngineService` that have special capabilities suitable for what's going on in component (B). +2. 子コンポヌネント (B)。コンポヌネント (B) は、コンポヌネント (B) で行われおいるこずに適した特別な機胜を持぀、 `CarService` ず `EngineService` の独自の _特殊な_ プロバむダヌを定矩したす。 -3. Child component (C) as a child of Component (B). Component (C) defines its own, even _more specialized_ provider for `CarService`. +3. コンポヌネント (B) の子である子コンポヌネント (C)。コンポヌネント (C) は、 `CarService` の独自の、さらに _特殊な_ プロバむダヌを定矩したす。 ```mermaid graph TD; @@ -1126,13 +1126,13 @@ classDef noShadow filter:none class COMPONENT_A,COMPONENT_B,COMPONENT_C noShadow ``` -Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself. +裏偎では、各コンポヌネントはコンポヌネント自䜓に定矩された、0、1たたは耇数のプロバむダヌで独自のむンゞェクタヌを蚭定したす。 -When you resolve an instance of `Car` at the deepest component (C), its injector produces: +最も深いコンポヌネント (C) で `Car` のむンスタンスを解決するず、そのむンゞェクタヌは次を生成したす。 -* An instance of `Car` resolved by injector (C) -* An `Engine` resolved by injector (B) -* Its `Tires` resolved by the root injector (A). +* むンゞェクタヌ (C) によっお解決された `Car` のむンスタンス +* むンゞェクタヌ (B) によっお解決された `Engine` +* ルヌトむンゞェクタヌ (A) によっお解決された `Tires`。 ```mermaid graph BT; @@ -1173,8 +1173,8 @@ style tires fill:#BDD7EE,color:#000 style RootInjector fill:#BDD7EE,color:#000 ``` -## More on dependency injection +## 䟝存性の泚入の詳现 - + diff --git a/prh.yml b/prh.yml index f45d3f196f..d7deb53b5f 100644 --- a/prh.yml +++ b/prh.yml @@ -5,7 +5,10 @@ rules: # 蚀い換え - expected: 䟝存性の泚入 - pattern: 䟝存性泚入 + pattern: + - 䟝存性泚入 + - 䟝存関係の泚入 + - 䟝存関係泚入 - expected: 䟝存性を泚入し pattern: 䟝存泚入し From 609eaf935d3b88a595920b724fbb7064ecc4af1d Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Sat, 20 Jul 2024 14:17:08 +0900 Subject: [PATCH 3/3] chore: translate large content by splitting --- tools/lib/fsutils.ts | 7 +++ tools/translate.ts | 115 ++++++++++++++++++++++++++++++------------- 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/tools/lib/fsutils.ts b/tools/lib/fsutils.ts index 1483d5a1dc..0502036211 100644 --- a/tools/lib/fsutils.ts +++ b/tools/lib/fsutils.ts @@ -1,3 +1,4 @@ +import { $ } from 'execa'; import { globby } from 'globby'; import { access, cp, readFile, rm, writeFile } from 'node:fs/promises'; @@ -33,3 +34,9 @@ export async function rename(oldPath: string, newPath: string) { await cp(oldPath, newPath); await rm(oldPath); } + +export async function getLineCount(path: string) { + return $`wc -l ${path}`.then(({ stdout }) => { + return parseInt(stdout.trim().split(' ')[0]); + }); +} diff --git a/tools/translate.ts b/tools/translate.ts index 27e38e90d8..5a8af38954 100644 --- a/tools/translate.ts +++ b/tools/translate.ts @@ -13,7 +13,7 @@ import assert from 'node:assert'; import { stat, writeFile } from 'node:fs/promises'; import { resolve } from 'node:path'; import { parseArgs } from 'node:util'; -import { glob } from './lib/fsutils'; +import { getLineCount, glob } from './lib/fsutils'; import { rootDir } from './lib/workspace'; const apiKey = process.env.GOOGLE_API_KEY; @@ -23,13 +23,13 @@ const fileManager = new GoogleAIFileManager(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-1.5-flash', systemInstruction: ` -あなたはWebフロント゚ンドに関する技術文曞の翻蚳アシスタントです。 -Markdownファむルを受け取り、英語を日本語に翻蚳した結果を出力しおください。 -翻蚳䜜業は以䞋のルヌルを遵守しおください。 -- 元のMarkdownの文曞構造を維持しおください。 +あなたは技術文曞の翻蚳アシスタントです。 +Markdown圢匏のテキストを受け取り、日本語に翻蚳しおください。以䞋のルヌルを遵守しおください。 +- 元のMarkdownの改行やむンデントの構造を維持しおください。 - 内容の説明は含めず、翻蚳結果のみを出力しおください。 - コヌドブロックの䞭身は翻蚳しないでください。 -- "TIP: ", "HELPFUL: ", "IMPORTANT: "など、ヒントや泚意曞きを瀺すプレフィックスは倉曎しないでください。 +- 行頭の特別なプレフィックス [TIP,HELPFUL,IMPORTANT,NOTE,QUESTION,TLDR,CRITICAL] は翻蚳しないでください。 +- prh.yml は日本語の校正ルヌルが曞かれたYAMLファむルです。このルヌルに埓っお翻蚳しおください。 `.trim(), }); @@ -81,35 +81,82 @@ async function translateFile(file: string, forceWrite = false) { displayName: `content.md`, }); // Execute translation - const result = await model.generateContentStream([ - { - fileData: { - mimeType: contentFile.file.mimeType, - fileUri: contentFile.file.uri, - }, - }, - { - fileData: { - mimeType: prhFile.file.mimeType, - fileUri: prhFile.file.uri, - }, - }, - `content.md を日本語に翻蚳しおください。`, - `prh.yml は日本語の校正ルヌルが曞かれたYAMLファむルです。ルヌルに埓っお翻蚳埌のテキストを修正しおください。`, - ]); - // Show translation result - process.stdout.write('\n----\n'); - const chunks: string[] = []; - for await (const chunk of result.stream) { - const text = chunk.text(); - chunks.push(text); - process.stdout.write(text); - } - process.stdout.write('\n----\n'); + consola.info(`翻蚳䞭...`); + const lineCount = await getLineCount(file); + if (lineCount < 500) { + const translatedContent = await model + .generateContent([ + { + fileData: { + mimeType: prhFile.file.mimeType, + fileUri: prhFile.file.uri, + }, + }, + { + fileData: { + mimeType: contentFile.file.mimeType, + fileUri: contentFile.file.uri, + }, + }, + `content.md を日本語に翻蚳しおください。`, + ]) + .then(({ response }) => response.text()); + await writeTranslatedContent(file, translatedContent, forceWrite); + } else { + consola.warn( + `ファむルが倧きいため、いく぀かの断片に分割しお翻蚳されたす。翻蚳埌の敎合性に泚意しおください。` + ); + const translationChunks: string[] = []; + const chat = await model.startChat({ history: [] }); + let count = 1; + const maxCount = Math.ceil(lineCount / 100); // 100行ごずに分割した回数より倚くなった堎合ぱラヌ + let lastTranslationChunk = await chat + .sendMessage([ + { + fileData: { + mimeType: prhFile.file.mimeType, + fileUri: prhFile.file.uri, + }, + }, + { + fileData: { + mimeType: contentFile.file.mimeType, + fileUri: contentFile.file.uri, + }, + }, + `content.md を日本語に翻蚳しおください。翻蚳結果のテキストを100行ず぀に分割しお。その1番目の郚分を出力しおください。`, + ]) + .then(({ response }) => response.text().trim()); + while (count < maxCount) { + consola.log(`\n---- 翻蚳結果 (${count}) ----\n`); + consola.log(lastTranslationChunk); + translationChunks.push(lastTranslationChunk); + translationChunks.push(``); - consola.success('翻蚳完了'); - const translatedContent = chunks.join(''); + // Continue translation + count++; + const chunk = await chat + .sendMessage( + `続けお、翻蚳結果の${count}番目の郚分を出力しおください。${count}番目が存圚しなければ「EOF」ず出力しおください` + ) + .then(({ response }) => response.text().trim()); + // Abort if infinite loop detected + if (chunk === 'EOF' || lastTranslationChunk === chunk) { + break; + } + lastTranslationChunk = chunk; + } + consola.success('翻蚳完了'); + const translatedContent = translationChunks.join('\n'); + await writeTranslatedContent(file, translatedContent, forceWrite); + } +} +async function writeTranslatedContent( + file: string, + content: string, + forceWrite = false +) { // 元のファむル拡匵子が .en.* の堎合は .* ずしお保存する const outFilePath = file.replace(/\.en\.([^.]+)$/, '.$1'); const save = @@ -121,7 +168,7 @@ async function translateFile(file: string, forceWrite = false) { if (!save) { return; } - await writeFile(outFilePath, translatedContent); + await writeFile(outFilePath, content); consola.success(`保存したした`); }