Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ability to generate content.json in multiple languages #48

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/out-tsc

# generated content
content.json
content.*.json

# dependencies
/node_modules
Expand Down
36 changes: 36 additions & 0 deletions TRANSLATION.md
Original file line number Diff line number Diff line change
@@ -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).
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 9 additions & 4 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
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';
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],
Expand All @@ -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<ApplicationState>) {
store.dispatch(new SetLangageCode(locale));
}
}
11 changes: 9 additions & 2 deletions src/app/checklist/state/checklist.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
8 changes: 7 additions & 1 deletion src/app/checklist/state/checklist.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down
20 changes: 13 additions & 7 deletions tools/build-checklist.ts
Original file line number Diff line number Diff line change
@@ -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);
});
15 changes: 15 additions & 0 deletions tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {},
Expand Down Expand Up @@ -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;
}
};