Browse Source

docs: Add more docs on translations

Michael Bromley 2 years ago
parent
commit
ea173c39a2
1 changed files with 104 additions and 4 deletions
  1. 104 4
      docs/docs/guides/developer-guide/translations/index.md

+ 104 - 4
docs/docs/guides/developer-guide/translations/index.md

@@ -1,14 +1,114 @@
 ---
-title: "Translation"
+title: "Translations"
 showtoc: true
 ---
 
-This section describes how to add new translations to the Vendure server.
+The following items in Vendure can be translated:
+
+- Entities which implement the [`Translatable`](/reference/typescript-api/entities/interfaces/#translatable) interface.
+- Admin UI text labels and messages
+- Server error message
+
+## Translatable entities
+
+The following entities implement the `Translatable` interface:
+
+- [Collection](/reference/typescript-api/entities/collection/)
+- [Country](/reference/typescript-api/entities/country/)
+- [Facet](/reference/typescript-api/entities/facet/)
+- [FacetValue](/reference/typescript-api/entities/facet-value/)
+- [PaymentMethod](/reference/typescript-api/entities/payment-method/)
+- [Product](/reference/typescript-api/entities/product/)
+- [ProductOption](/reference/typescript-api/entities/product-option/)
+- [ProductOptionGroup](/reference/typescript-api/entities/product-option-group/)
+- [ProductVariant](/reference/typescript-api/entities/product-variant/)
+- [Promotion](/reference/typescript-api/entities/promotion/)
+- [Province](/reference/typescript-api/entities/province/)
+- [Region](/reference/typescript-api/entities/region/)
+- [ShippingMethod](/reference/typescript-api/entities/shipping-method/)
+
+To understand how translatable entities are implemented, let's take a look at a simplified version of the `Facet` entity:
+
+```ts
+@Entity()
+export class Facet extends VendureEntity implements Translatable {
+    
+    // highlight-next-line
+    name: LocaleString;
+
+    @Column({ unique: true })
+    code: string;
+
+    // highlight-next-line
+    @OneToMany(type => FacetTranslation, translation => translation.base, { eager: true })
+    // highlight-next-line
+    translations: Array<Translation<Facet>>;
+}
+```
+
+All translatable entities have a `translations` field which is a relation to the translations. Any fields that are to be translated are of type `LocaleString`, and **do note have a `@Column()` decorator**. This is because the `name` field here does not in fact exist in the database in the `facet` table. Instead, it belongs to the `facet_translations` table, which brings us to the `FacetTranslation` entity (again simplified for clarity):
+
+```ts
+@Entity()
+export class FacetTranslation extends VendureEntity implements Translation<Facet> {
+
+    @Column('varchar') languageCode: LanguageCode;
+
+    // highlight-next-line
+    @Column() name: string;
+
+    @Index()
+    @ManyToOne(type => Facet, base => base.translations, { onDelete: 'CASCADE' })
+    base: Facet;
+}
+```
+
+Thus there is a one-to-many relation between `Facet` and `FacetTranslation`, which allows Vendure to handle multiple translations of the same entity. The `FacetTranslation` entity also implements the `Translation` interface, which requires the `languageCode` field and a reference to the base entity.
+
+### Loading translatable entities
+
+If your plugin needs to load a translatable entity, you will need to use the [`TranslatorService`](/reference/typescript-api/service-helpers/translator-service/) to hydrate all the `LocaleString` fields will the actual translated values from the correct translation.
+
+For example, if you are loading a `Facet` entity, you would do the following:
+
+```ts
+import { Facet } from '@vendure/core';
+import { LanguageCode, RequestContext, TranslatorService, TransactionalConnection } from '@vendure/core';
+
+@Injectable()
+export class MyService {
+    
+    constructor(private connection: TransactionalConnection, private translator: TranslatorService) {}
+
+    async getFacet(ctx: RequestContext, id: ID): Promise<Facet | undefined> {
+        const facet = await this.connection.getRepository(ctx, Facet).findOne(id);
+        if (facet) {
+            // highlight-next-line
+            return this.translatorService.translate(facet, ctx);
+        }
+    }
+    
+    async getFacets(ctx: RequestContext): Promise<Facet[]> {
+        // highlight-next-line
+        const facets = await this.connection.getRepository(ctx, Facet).find();
+        // highlight-next-line
+        return Promise.all(facets.map(facet => this.translatorService.translate(facet, ctx)));
+    }
+}
+```
+## Admin UI translations
+
+See the [Adding Admin UI Translations guide](/guides/extending-the-admin-ui/adding-ui-translations/).
+
+## Server message translations
+
+Let's say you've implemented some custom server-side functionality as part of a plugin. You may be returning custom errors or other messages. Here's how you can
+provide these messages in multiple languages.
 
 Using [`addTranslation`](/reference/typescript-api/common/i18n-service/#addtranslation) inside the `onApplicationBootstrap` ([Nestjs lifecycle hooks](https://docs.nestjs.com/fundamentals/lifecycle-events)) of a Plugin is the easiest way to add new translations.
 While Vendure is only using `error`, `errorResult` and `message` resource keys you are free to use your own.
 
-## Translatable Error
+### Translatable Error
 This example shows how to create a custom translatable error
 ```ts
 /**
@@ -57,7 +157,7 @@ export class TranslationTestPlugin implements OnApplicationBootstrap {
 To receive an error in a specific language you need to use the `languageCode` query parameter
 `query(QUERY_WITH_ERROR_RESULT, { variables }, { languageCode: LanguageCode.de });`
 
-## Use translations
+### Use translations
 
 Vendure uses the internationalization-framework [i18next](https://www.i18next.com/).