-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- add docs for using translations in 3 different ways: 1. single Locale (other than English) 2. with I18Next 3. with custom Translate Service
- Loading branch information
1 parent
fb3d8b7
commit 49523d1
Showing
4 changed files
with
299 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
### Demo | ||
[Demo Page](https://ghiscoding.github.io/slickgrid-universal/#/example07) / [Demo Component](https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/vite-demo-vanilla-bundle/src/examples/example07.ts) | ||
|
||
### Installation | ||
Install the `i18next` library with a backend loader, typically `i18next-xhr-backend` | ||
|
||
##### Install NPM package | ||
```ts | ||
npm install i18next i18next-xhr-backend | ||
``` | ||
|
||
##### Main.ts | ||
###### configure i18n loader with assets folder | ||
```ts | ||
import i18n from 'i18next'; | ||
import Backend from 'i18next-http-backend'; | ||
|
||
i18n | ||
.use(Backend) | ||
.init({ | ||
// the translations (tip move them in a JSON file and import them or even better, manage them via a UI | ||
// backend: { | ||
// loadPath: 'assets/locales/{{lng}}/{{ns}}.json', | ||
// }, | ||
resources: { | ||
en: { translation: localeEn }, | ||
fr: { translation: localeFr }, | ||
}, | ||
lng: 'en', | ||
fallbackLng: 'en', | ||
debug: false, | ||
interpolation: { | ||
escapeValue: false | ||
} | ||
}); | ||
``` | ||
|
||
#### Class sample | ||
You need to add a translation key via the property `headerKey` to each column definition, for example: `headerKey: 'TITLE'` | ||
|
||
##### Note | ||
For the `Select` Filter, you will use `labelKey` instead of `label`. Anytime a translation key will come in play, we will add the word `key` to the end (hence `headerKey`, `labelKey`, more to come...) | ||
|
||
```ts | ||
import { Formatters } from '@slickgrid-universal/common'; | ||
import i18next, { TFunction } from 'i18next'; | ||
|
||
// create a custom translate Formatter | ||
function taskTranslateFormatter: Formatter = (row, cell, value, columnDef, dataContext, grid) => { | ||
const gridOptions: GridOption = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}; | ||
return gridOptions.i18n?.t('TASK_X', { x: value }) ?? ''; | ||
} | ||
|
||
export class Example { | ||
constructor() { | ||
// define the grid options & columns and then create the grid itself | ||
this.defineGrid(); | ||
} | ||
|
||
// Define grid Options and Columns | ||
// provide a headerKey for each column and enableTranslate to True in GridOption | ||
defineGrid() { | ||
const columnDefinitions = [ | ||
{ id: 'title', name: 'Title', field: 'title', headerKey: 'TITLE', formatter: this.taskTranslateFormatter, sortable: true, minWidth: 100 }, | ||
{ id: 'duration', name: 'Duration (days)', field: 'duration', headerKey: 'DURATION', sortable: true, minWidth: 100 }, | ||
{ id: 'start', name: 'Start', field: 'start', headerKey: 'START', formatter: Formatters.dateIso, minWidth: 100 }, | ||
{ id: 'finish', name: 'Finish', field: 'finish', headerKey: 'FINISH', formatter: Formatters.dateIso, minWidth: 100 }, | ||
{ id: 'completed', name: 'Completed', field: 'completed', headerKey: 'COMPLETED', formatter: Formatters.translate, params: { i18n: i18next }, sortable: true, minWidth: 100 } | ||
// OR via your own custom translate formatter | ||
// { id: 'completed', name: 'Completed', field: 'completed', headerKey: 'COMPLETED', formatter: translateFormatter, sortable: true, minWidth: 100 } | ||
]; | ||
const gridOptions = { | ||
enableTranslate: true, | ||
i18n: i18next, | ||
}; | ||
} | ||
} | ||
``` | ||
|
||
#### Custom Formatter (cell values) | ||
You can define your own custom Formatter by providing the `i18n` Service into the Formatter and using the `.tr()` function to translate the cell value. | ||
```ts | ||
const taskTranslateFormatter: Formatter = (row, cell, value, columnDef, dataContext, grid) => { | ||
const gridOptions: GridOption = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}; | ||
return gridOptions.i18n?.t('TASK_X', { x: value }) ?? ''; | ||
} | ||
``` | ||
|
||
#### Using Formatters.Translate | ||
Instead of defining a custom formatter over and over, you could also use the built-in `Formatters.translate`. However for the formatter to work, you need to provide the `i18n` Service instance, you can do so using the `params` properties which is made to pass any type of data, however you need to pass it with this structure: `params: { i18n: i18next } `. | ||
```ts | ||
const columnDefinitions = [ | ||
{ | ||
id: 'title', | ||
name: 'Title', | ||
field: 'title', | ||
headerKey: 'TITLE', | ||
formatter: Formatters.translate, | ||
params: { i18n: i18next } // provide the `i18n instance through the params.i18n property | ||
} | ||
]; | ||
``` | ||
|
||
#### Passing `i18n` in the Grid Options for Formatter | ||
The best and quick way to pass the `i18n` service is to pass it through the generic `params` grid option. However make sure that you use the following structure: `params: { i18n: i18next } `. | ||
```ts | ||
const gridOptions = { | ||
enableTranslate: true, | ||
params: { i18n: i18next } // provide the `i18n instance through the params.i18n property | ||
}; | ||
``` | ||
|
||
#### Locales | ||
The final step is of course the actual translations. There's multiple ways to copy them to your `assets` folder. See below for a few ways: | ||
1. Manually copy the translation keys/values | ||
2. Manually copy the JSON files to your `assets` folder | ||
3. Or modify your `package.json` and add a script to copy the JSON files to your `assets` folder | ||
- install NPM packages `cross-env` and `copyfiles` (`npm install copy-files cross-env`) | ||
- add a new script in your `package.json` | ||
- run the below script **once** with `npm run copy:i18n` and you should now have the JSON files in your `src/assets` folder | ||
|
||
If you want to manually re-create the translation in your own files, the list of translations that you will need are displayed in the asset i18n translation folder (from that file, you need all translations shown before the 'BILLING', the next few ones are for the demo page only). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
## Description | ||
Most of example that you will find across this library were made with a Translation Service or `I18N` (dynamic translation) support. However a few users of the lib only use 1 single locale (English or any other locale). Since not all users requires multiple translations, it is now possible to use the project without any Translation Service at all. What is the difference with/without Translation Service or `I18N`? Not much, the only difference is that `I18N` is an optional dependency, it will simply try to use Custom Locales, you can provide your own locales (see instruction below), or if none are provided it will use the English locales by default. | ||
|
||
## Installation | ||
There are 2 ways of using and defining Custom Locales, see below on how to achieve that. | ||
|
||
### 1. Define your Custom Locales | ||
#### English Locale | ||
English is the default, if that is the locale you want to use, then there's nothing to do, move along... | ||
|
||
#### Any other Locales (not English) | ||
To use any other Locales, you will need to create a TypeScript (or JavaScript) of all the Locale Texts required for the library to work properly (if you forget to define a locale text, it will simply show up in English). For example, if we define a French Locale, it would look like this (for the complete list of required field take a look at the default [English Locale](https://github.com/ghiscoding/angular-slickgrid-demos/blob/master/bootstrap5-demo-with-locales/src/app/locales/en.ts) of Angular-Slickgrid) | ||
|
||
```ts | ||
// localeFrench.ts or fr.ts | ||
export const localeFrench = { | ||
// texte requis | ||
TEXT_ALL_SELECTED: 'Tout sélectionnés', | ||
TEXT_CANCEL: 'Annuler', | ||
TEXT_CLEAR_ALL_FILTERS: 'Supprimer tous les filtres', | ||
TEXT_CLEAR_ALL_SORTING: 'Supprimer tous les tris', | ||
// ... the rest of the text | ||
``` | ||
#### 2. Use the Custom Locales | ||
##### Through the Grid Option of any grid | ||
You can alternatively provide Custom Locales through any grid declaration through the `locales` Grid Options (it's the same as the global one, except that it's per grid) | ||
```ts | ||
import { localeFrench } from 'locales/fr'; | ||
|
||
export class MyGrid { | ||
defineGrid() { | ||
const columnDefinitions = [ /* ... */ ]; | ||
|
||
const gridOptions = { | ||
enableAutoResize: true, | ||
|
||
// provide Custom Locale to this grid only | ||
locales: localeFrench | ||
}; | ||
} | ||
} | ||
``` | ||
|
||
#### 3. Use the lib (without I18N) | ||
There's nothing else to do, just use the library without defining or providing I18N and you're good to go. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
### Demo | ||
[Demo Page](https://ghiscoding.github.io/slickgrid-universal/#/example07) / [Demo Component](https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/vite-demo-vanilla-bundle/src/examples/example07.ts) | ||
|
||
### Installation | ||
|
||
You can create your own Translate Service, for example installing the `whatwg-fetch` library to load JSON files for translations. | ||
|
||
##### Install NPM package | ||
|
||
```ts | ||
npm install whatwg-fetch | ||
``` | ||
|
||
##### Main.ts | ||
|
||
You must make sure to implement all functions of the `TranslaterService` interface. | ||
|
||
```ts | ||
export class TranslateService implements TranslaterService { | ||
/** Method to return the current language used by the App */ | ||
getCurrentLanguage(): string {} | ||
|
||
/** Method which receives a translation key and returns the translated value from that key */ | ||
translate(translationKey: string, params?: any): string {} | ||
|
||
/** Method to set the language to use in the App and Translate Service */ | ||
use(language: string): Promise<any> | any {} | ||
} | ||
``` | ||
|
||
#### Class sample | ||
You need to add a translation key via the property `headerKey` to each column definition, for example: `headerKey: 'TITLE'` | ||
|
||
##### Note | ||
For the `Select` Filter, you will use `labelKey` instead of `label`. Anytime a translation key will come in play, we will add the word `key` to the end (hence `headerKey`, `labelKey`, more to come...) | ||
|
||
##### Load App | ||
|
||
Load the App (i.e.: `main.ts`) and instantiate the `TranslateService` | ||
|
||
```ts | ||
class Main { | ||
constructor(private renderer: Renderer) { } | ||
|
||
async loadApp() { | ||
const translate = new TranslateService(); | ||
translate.setup({ | ||
loadPath: 'i18n/{{lang}}.json', | ||
lang: 'en' | ||
}); | ||
await translate.use('en'); | ||
|
||
// it might be better to use proper Dependency Injection | ||
// but for now let's use the window object to save keep a reference to our instantiated service | ||
(<any>window).TranslateService = translate; | ||
|
||
// ... do other things | ||
} | ||
} | ||
``` | ||
|
||
##### Use it | ||
|
||
```ts | ||
import { Formatters } from '@slickgrid-universal/common'; | ||
|
||
// create a custom translate Formatter | ||
function taskTranslateFormatter: Formatter = (row, cell, value, columnDef, dataContext) => { | ||
return this.translateService.translate('TASK_X', { x: value }) ?? ''; | ||
} | ||
|
||
export class Example { | ||
constructor() { | ||
// define the grid options & columns and then create the grid itself | ||
this.defineGrid(); | ||
} | ||
|
||
// Define grid Options and Columns | ||
// provide a headerKey for each column and enableTranslate to True in GridOption | ||
defineGrid() { | ||
const columnDefinitions = [ | ||
{ id: 'title', name: 'Title', field: 'title', headerKey: 'TITLE', formatter: this.taskTranslateFormatter, sortable: true, minWidth: 100 }, | ||
{ id: 'duration', name: 'Duration (days)', field: 'duration', headerKey: 'DURATION', sortable: true, minWidth: 100 }, | ||
{ id: 'start', name: 'Start', field: 'start', headerKey: 'START', formatter: Formatters.dateIso, minWidth: 100 }, | ||
{ id: 'finish', name: 'Finish', field: 'finish', headerKey: 'FINISH', formatter: Formatters.dateIso, minWidth: 100 }, | ||
{ id: 'completed', name: 'Completed', field: 'completed', headerKey: 'COMPLETED', formatter: Formatters.translate, params: { i18n: this.translateService }, sortable: true, minWidth: 100 } | ||
// OR via your own custom translate formatter | ||
// { id: 'completed', name: 'Completed', field: 'completed', headerKey: 'COMPLETED', formatter: translateFormatter, sortable: true, minWidth: 100 } | ||
]; | ||
|
||
const gridOptions = { | ||
enableTranslate: true, | ||
translater: this.translateService, | ||
}; | ||
} | ||
} | ||
``` | ||
|
||
#### Custom Formatter (cell values) | ||
|
||
You can define your own custom Formatter by providing the `TranslateService` Service into the Formatter and using the `.translate(key)` function to translate the cell value. | ||
|
||
```ts | ||
const taskTranslateFormatter: Formatter = (row, cell, value, columnDef, dataContext, grid) => { | ||
return this.translateService.translate('TASK_X', { x: value }) ?? ''; | ||
} | ||
``` | ||
|
||
#### Using Formatters.Translate | ||
Instead of defining a custom formatter over and over, you could also use the built-in `Formatters.translate`. However for the formatter to work, you need to provide the `TranslateService` instance, you can do so using the `params` properties which is made to pass any type of data. | ||
|
||
#### Passing `translater` in the Grid Options for the Translate Service | ||
|
||
```ts | ||
const gridOptions = { | ||
enableTranslate: true, | ||
translater: this.translateService, // pass the TranslateService instance to the grid | ||
}; | ||
``` |