diff --git a/.gitignore b/.gitignore index 11c8363..3921b7e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ /out-tsc # generated content -content.json +content.*.json # dependencies /node_modules diff --git a/TRANSLATION.md b/TRANSLATION.md new file mode 100644 index 0000000..efbe662 --- /dev/null +++ b/TRANSLATION.md @@ -0,0 +1,36 @@ +# Translation Guide + +## Add languages + +The following tasks are required to add a new language. +[See available code here](https://github.com/angular/angular/tree/master/packages/common/locales). + +- Add word translation file in `src/assets/i18n/[lang-code].json`. +- Add languages to `langages`, an array of `tools/utils.ts` files. +- Register langage code of the language to be added to `translocoConfig()` in `src/app/app.module.ts`. +- Make a target language directory by copying `en-US` in the content directory. And then run `yarn build-content`. + +Hooray! Now you can choose a new language. + +## Do translation + +There are two types of translation: translation of the application using [transloco](https://netbasal.gitbook.io/transloco/) and translation of the main content composed of markdown. + +### Application translation + +Please read the [transloco](https://netbasal.gitbook.io/transloco/) documentation once. + +Translate the app by editing `src/assets/i18n/[lang-code].json`. + +### Translation of content + +Translation of content is editing files in the `content/[lang-code]` directory. + +You don't have to make all the files at once. but when it's missing it will be displayed in original English. + +**Note:** If you set char such as `*` or `@` at the beginning of metadata such as `title:`, the translation will be broken. +Use double-byte characters or devise a text. + +## Reflect the translated content + +See [CONTRIBUTING.md](https://github.com/angular-checklist/angular-checklist/blob/master/CONTRIBUTING.md). diff --git a/content/architecture/.category b/content/en-US/architecture/.category similarity index 100% rename from content/architecture/.category rename to content/en-US/architecture/.category diff --git a/content/architecture/never-mutate-objects.md b/content/en-US/architecture/never-mutate-objects.md similarity index 100% rename from content/architecture/never-mutate-objects.md rename to content/en-US/architecture/never-mutate-objects.md diff --git a/content/architecture/provide-shared-services-on-root-level.md b/content/en-US/architecture/provide-shared-services-on-root-level.md similarity index 100% rename from content/architecture/provide-shared-services-on-root-level.md rename to content/en-US/architecture/provide-shared-services-on-root-level.md diff --git a/content/architecture/put-business-logic-into-services.md b/content/en-US/architecture/put-business-logic-into-services.md similarity index 100% rename from content/architecture/put-business-logic-into-services.md rename to content/en-US/architecture/put-business-logic-into-services.md diff --git a/content/architecture/use-descriptive-file-names.md b/content/en-US/architecture/use-descriptive-file-names.md similarity index 100% rename from content/architecture/use-descriptive-file-names.md rename to content/en-US/architecture/use-descriptive-file-names.md diff --git a/content/architecture/use-smart-and-dumb-components.md b/content/en-US/architecture/use-smart-and-dumb-components.md similarity index 100% rename from content/architecture/use-smart-and-dumb-components.md rename to content/en-US/architecture/use-smart-and-dumb-components.md diff --git a/content/components/.category b/content/en-US/components/.category similarity index 100% rename from content/components/.category rename to content/en-US/components/.category diff --git a/content/components/clean-up-resource-in-ng-on-destroy.md b/content/en-US/components/clean-up-resource-in-ng-on-destroy.md similarity index 100% rename from content/components/clean-up-resource-in-ng-on-destroy.md rename to content/en-US/components/clean-up-resource-in-ng-on-destroy.md diff --git a/content/components/dont-use-property-bindings-to-pass-static-strings.md b/content/en-US/components/dont-use-property-bindings-to-pass-static-strings.md similarity index 100% rename from content/components/dont-use-property-bindings-to-pass-static-strings.md rename to content/en-US/components/dont-use-property-bindings-to-pass-static-strings.md diff --git a/content/components/minimize-logic-in-templates.md b/content/en-US/components/minimize-logic-in-templates.md similarity index 100% rename from content/components/minimize-logic-in-templates.md rename to content/en-US/components/minimize-logic-in-templates.md diff --git a/content/components/ng-oninit-vs-constructor.md b/content/en-US/components/ng-oninit-vs-constructor.md similarity index 100% rename from content/components/ng-oninit-vs-constructor.md rename to content/en-US/components/ng-oninit-vs-constructor.md diff --git a/content/components/only-manipulate-the-dom-via-the-renderer.md b/content/en-US/components/only-manipulate-the-dom-via-the-renderer.md similarity index 100% rename from content/components/only-manipulate-the-dom-via-the-renderer.md rename to content/en-US/components/only-manipulate-the-dom-via-the-renderer.md diff --git a/content/general/.category b/content/en-US/general/.category similarity index 100% rename from content/general/.category rename to content/en-US/general/.category diff --git a/content/general/use-latest-version-of-everything.md b/content/en-US/general/use-latest-version-of-everything.md similarity index 100% rename from content/general/use-latest-version-of-everything.md rename to content/en-US/general/use-latest-version-of-everything.md diff --git a/content/http/.category b/content/en-US/http/.category similarity index 100% rename from content/http/.category rename to content/en-US/http/.category diff --git a/content/http/dont-reimport-httpclientmodule.md b/content/en-US/http/dont-reimport-httpclientmodule.md similarity index 100% rename from content/http/dont-reimport-httpclientmodule.md rename to content/en-US/http/dont-reimport-httpclientmodule.md diff --git a/content/ngrx/.category b/content/en-US/ngrx/.category similarity index 100% rename from content/ngrx/.category rename to content/en-US/ngrx/.category diff --git a/content/ngrx/action-hygiene.md b/content/en-US/ngrx/action-hygiene.md similarity index 100% rename from content/ngrx/action-hygiene.md rename to content/en-US/ngrx/action-hygiene.md diff --git a/content/ngrx/actions-are-defined-as-classes.md b/content/en-US/ngrx/actions-are-defined-as-classes.md similarity index 100% rename from content/ngrx/actions-are-defined-as-classes.md rename to content/en-US/ngrx/actions-are-defined-as-classes.md diff --git a/content/ngrx/do-not-put-everything-in-the-store.md b/content/en-US/ngrx/do-not-put-everything-in-the-store.md similarity index 100% rename from content/ngrx/do-not-put-everything-in-the-store.md rename to content/en-US/ngrx/do-not-put-everything-in-the-store.md diff --git a/content/ngrx/dont-store-state-that-can-be-derived.md b/content/en-US/ngrx/dont-store-state-that-can-be-derived.md similarity index 100% rename from content/ngrx/dont-store-state-that-can-be-derived.md rename to content/en-US/ngrx/dont-store-state-that-can-be-derived.md diff --git a/content/ngrx/reducers-are-pure-functions.md b/content/en-US/ngrx/reducers-are-pure-functions.md similarity index 100% rename from content/ngrx/reducers-are-pure-functions.md rename to content/en-US/ngrx/reducers-are-pure-functions.md diff --git a/content/ngrx/use-entity-pattern.md b/content/en-US/ngrx/use-entity-pattern.md similarity index 100% rename from content/ngrx/use-entity-pattern.md rename to content/en-US/ngrx/use-entity-pattern.md diff --git a/content/ngrx/use-selectors.md b/content/en-US/ngrx/use-selectors.md similarity index 100% rename from content/ngrx/use-selectors.md rename to content/en-US/ngrx/use-selectors.md diff --git a/content/performance/.category b/content/en-US/performance/.category similarity index 100% rename from content/performance/.category rename to content/en-US/performance/.category diff --git a/content/performance/track-by-option-on-ng-for.md b/content/en-US/performance/track-by-option-on-ng-for.md similarity index 100% rename from content/performance/track-by-option-on-ng-for.md rename to content/en-US/performance/track-by-option-on-ng-for.md diff --git a/content/performance/use-aot-compilation.md b/content/en-US/performance/use-aot-compilation.md similarity index 100% rename from content/performance/use-aot-compilation.md rename to content/en-US/performance/use-aot-compilation.md diff --git a/content/performance/use-on-push-cd-strategy.md b/content/en-US/performance/use-on-push-cd-strategy.md similarity index 100% rename from content/performance/use-on-push-cd-strategy.md rename to content/en-US/performance/use-on-push-cd-strategy.md diff --git a/content/router/.category b/content/en-US/router/.category similarity index 100% rename from content/router/.category rename to content/en-US/router/.category diff --git a/content/router/add-404-route.md b/content/en-US/router/add-404-route.md similarity index 100% rename from content/router/add-404-route.md rename to content/en-US/router/add-404-route.md diff --git a/content/router/default-route.md b/content/en-US/router/default-route.md similarity index 100% rename from content/router/default-route.md rename to content/en-US/router/default-route.md diff --git a/content/router/lazy-load-feature-modules.md b/content/en-US/router/lazy-load-feature-modules.md similarity index 100% rename from content/router/lazy-load-feature-modules.md rename to content/en-US/router/lazy-load-feature-modules.md diff --git a/content/router/protect-restricted-pages-with-guards.md b/content/en-US/router/protect-restricted-pages-with-guards.md similarity index 100% rename from content/router/protect-restricted-pages-with-guards.md rename to content/en-US/router/protect-restricted-pages-with-guards.md diff --git a/content/router/use-preloading-strategy.md b/content/en-US/router/use-preloading-strategy.md similarity index 100% rename from content/router/use-preloading-strategy.md rename to content/en-US/router/use-preloading-strategy.md diff --git a/content/rxjs/.category b/content/en-US/rxjs/.category similarity index 100% rename from content/rxjs/.category rename to content/en-US/rxjs/.category diff --git a/content/rxjs/avoid-nested-subscriptions.md b/content/en-US/rxjs/avoid-nested-subscriptions.md similarity index 100% rename from content/rxjs/avoid-nested-subscriptions.md rename to content/en-US/rxjs/avoid-nested-subscriptions.md diff --git a/content/rxjs/pipeable-operators.md b/content/en-US/rxjs/pipeable-operators.md similarity index 100% rename from content/rxjs/pipeable-operators.md rename to content/en-US/rxjs/pipeable-operators.md diff --git a/content/rxjs/takeuntil-operator.md b/content/en-US/rxjs/takeuntil-operator.md similarity index 100% rename from content/rxjs/takeuntil-operator.md rename to content/en-US/rxjs/takeuntil-operator.md diff --git a/content/rxjs/use-async-pipe.md b/content/en-US/rxjs/use-async-pipe.md similarity index 100% rename from content/rxjs/use-async-pipe.md rename to content/en-US/rxjs/use-async-pipe.md diff --git a/content/rxjs/use-ngifas.md b/content/en-US/rxjs/use-ngifas.md similarity index 100% rename from content/rxjs/use-ngifas.md rename to content/en-US/rxjs/use-ngifas.md diff --git a/content/rxjs/use-switchMap-only-when-you-need-cancellation.md b/content/en-US/rxjs/use-switchMap-only-when-you-need-cancellation.md similarity index 100% rename from content/rxjs/use-switchMap-only-when-you-need-cancellation.md rename to content/en-US/rxjs/use-switchMap-only-when-you-need-cancellation.md diff --git a/content/tooling/.category b/content/en-US/tooling/.category similarity index 100% rename from content/tooling/.category rename to content/en-US/tooling/.category diff --git a/content/tooling/compodoc.md b/content/en-US/tooling/compodoc.md similarity index 100% rename from content/tooling/compodoc.md rename to content/en-US/tooling/compodoc.md diff --git a/content/tooling/use-angular-cli.md b/content/en-US/tooling/use-angular-cli.md similarity index 100% rename from content/tooling/use-angular-cli.md rename to content/en-US/tooling/use-angular-cli.md diff --git a/content/tooling/use-prettier.md b/content/en-US/tooling/use-prettier.md similarity index 100% rename from content/tooling/use-prettier.md rename to content/en-US/tooling/use-prettier.md diff --git a/content/typescript/.category b/content/en-US/typescript/.category similarity index 100% rename from content/typescript/.category rename to content/en-US/typescript/.category diff --git a/content/typescript/avoid-using-any.md b/content/en-US/typescript/avoid-using-any.md similarity index 100% rename from content/typescript/avoid-using-any.md rename to content/en-US/typescript/avoid-using-any.md diff --git a/content/typescript/define-interfaces-for-models.md b/content/en-US/typescript/define-interfaces-for-models.md similarity index 100% rename from content/typescript/define-interfaces-for-models.md rename to content/en-US/typescript/define-interfaces-for-models.md diff --git a/content/typescript/define-types-at-the-non-typed-boundaries.md b/content/en-US/typescript/define-types-at-the-non-typed-boundaries.md similarity index 100% rename from content/typescript/define-types-at-the-non-typed-boundaries.md rename to content/en-US/typescript/define-types-at-the-non-typed-boundaries.md diff --git a/content/typescript/move-common-types-to-interfaces.md b/content/en-US/typescript/move-common-types-to-interfaces.md similarity index 100% rename from content/typescript/move-common-types-to-interfaces.md rename to content/en-US/typescript/move-common-types-to-interfaces.md diff --git a/content/typescript/use-type-inference.md b/content/en-US/typescript/use-type-inference.md similarity index 100% rename from content/typescript/use-type-inference.md rename to content/en-US/typescript/use-type-inference.md diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b421ff8..b8d24a7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,9 +1,9 @@ -import { NgModule } from '@angular/core'; +import { NgModule, LOCALE_ID, Inject } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { PreloadAllModules, RouterModule } from '@angular/router'; import { StoreRouterConnectingModule } from '@ngrx/router-store'; -import { StoreModule } from '@ngrx/store'; +import { StoreModule, Store } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { environment } from '../environments/environment'; import { AppComponent } from './app.component'; @@ -11,7 +11,8 @@ import { APP_ROUTES } from './app.routes'; import { ChecklistModule } from './checklist/checklist.module'; import { CustomMaterialModule } from './custom-material.module'; import { ProjectsModule } from './projects/projects.module'; -import { META_REDUCERS, ROOT_REDUCER } from './state/app.state'; +import { META_REDUCERS, ROOT_REDUCER, ApplicationState } from './state/app.state'; +import { SetLangageCode } from './checklist/state/checklist.actions'; @NgModule({ declarations: [AppComponent], @@ -33,4 +34,8 @@ import { META_REDUCERS, ROOT_REDUCER } from './state/app.state'; ], bootstrap: [AppComponent] }) -export class AppModule {} +export class AppModule { + constructor(@Inject(LOCALE_ID) locale: string, store: Store) { + store.dispatch(new SetLangageCode(locale)); + } +} diff --git a/src/app/checklist/state/checklist.actions.ts b/src/app/checklist/state/checklist.actions.ts index 133a2b7..852bb1e 100644 --- a/src/app/checklist/state/checklist.actions.ts +++ b/src/app/checklist/state/checklist.actions.ts @@ -4,7 +4,8 @@ import { ChecklistFilter } from '../models/checklist.model'; export enum ChecklistActionTypes { SET_CATEGORIES_FILTER = '[Checklist] set categories filter', SET_FAVORITES_FILTER = '[Checklist] set favroites filter', - TOGGLE_EDIT_MODE = '[Checklist] toggle edit mode' + TOGGLE_EDIT_MODE = '[Checklist] toggle edit mode', + SET_LANG_CODE = '[Checklist] set langage code ' } export class SetCategoriesFilter implements Action { @@ -25,4 +26,10 @@ export class ToggleEditMode implements Action { constructor() {} } -export type ChecklistActions = SetCategoriesFilter | SetFavoritesFilter | ToggleEditMode; +export class SetLangageCode implements Action { + readonly type = ChecklistActionTypes.SET_LANG_CODE; + + constructor(public payload: string) {} +} + +export type ChecklistActions = SetCategoriesFilter | SetFavoritesFilter | ToggleEditMode | SetLangageCode; diff --git a/src/app/checklist/state/checklist.reducer.ts b/src/app/checklist/state/checklist.reducer.ts index fbae7e5..a1c1f23 100644 --- a/src/app/checklist/state/checklist.reducer.ts +++ b/src/app/checklist/state/checklist.reducer.ts @@ -2,7 +2,7 @@ import { Filter } from '../models/checklist.model'; import { ChecklistActions, ChecklistActionTypes } from './checklist.actions'; import { ChecklistState } from './checklist.state'; -const CHECKLIST = require('../../../assets/content.json'); +const CHECKLIST = require('../../../assets/content.en-US.json'); export const INITIAL_STATE: ChecklistState = { ...CHECKLIST, @@ -26,6 +26,12 @@ export function checklistReducer(state = INITIAL_STATE, action: ChecklistActions ...state, editMode: !state.editMode }; + case ChecklistActionTypes.SET_LANG_CODE: + return { + ...state, + ...require(`../../../assets/content.${action.payload || 'en-US'}.json`), + editMode: !state.editMode + }; default: return state; } diff --git a/tools/build-checklist.ts b/tools/build-checklist.ts index 407b127..135ee2f 100644 --- a/tools/build-checklist.ts +++ b/tools/build-checklist.ts @@ -1,13 +1,19 @@ import { join } from 'path'; -import { buildChecklist, dumpDataToDisk, printSuccess } from './utils'; +import { buildChecklist, dumpDataToDisk, printSuccess, langages, localeEnUS, transrateDeepMerge } from './utils'; const CONTENT_FOLDER = join(__dirname, '../content'); const ASSET_FOLDER = join(__dirname, '../src/assets'); -buildChecklist(CONTENT_FOLDER).then(checklist => { - if (checklist) { - dumpDataToDisk('content', checklist, ASSET_FOLDER); - printSuccess('Content was successfully compiled', 'Done'); - process.exit(0); - } +Promise.all( + langages.map(async lang => { + const checklist = await buildChecklist(join(CONTENT_FOLDER, lang)); + const checklistEnUS = await buildChecklist(join(CONTENT_FOLDER, localeEnUS)); + + if (checklist && checklistEnUS) { + dumpDataToDisk(`content.${lang}`, transrateDeepMerge(checklistEnUS, checklist), ASSET_FOLDER); + } + }) +).then(() => { + printSuccess('Content was successfully compiled', 'Done'); + process.exit(0); }); diff --git a/tools/utils.ts b/tools/utils.ts index 75dfb95..7654379 100644 --- a/tools/utils.ts +++ b/tools/utils.ts @@ -8,6 +8,9 @@ import hash = require('shorthash'); markdown.use(convertHeadingsPlugin); +export const localeEnUS = 'en-US'; +export const langages = [localeEnUS]; + export const buildChecklist = async contentFolder => { const checklist = { categories: {}, @@ -126,3 +129,15 @@ export const throwError = (message: string) => { export const logWarning = (message: string) => { console.log(`${chalk.yellow(message)}`); }; + +export const transrateDeepMerge = (target, source) => { + if (typeof source === 'undefined') { + return target; + } else if (target && typeof target === 'object' && !Array.isArray(target)) { + return Object.keys(target) + .map(key => ({ [key]: transrateDeepMerge(target[key], source[key]) })) + .reduce((p, c) => ({ ...p, ...c }), {}); + } else { + return source; + } +};