Skip to content

Commit

Permalink
feat(package): ngsm i18n module
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianmusial committed May 3, 2020
0 parents commit a6d823d
Show file tree
Hide file tree
Showing 23 changed files with 10,646 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# compiled output
/dist
/tmp
/out-tsc

# dependencies
/node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<p align="center">
<a href="https://github.com/ng-sm">
<img src="https://avatars2.githubusercontent.com/u/64587411?s=150">
</a>
</p>
<p align="center">
I18n module based on the @ngx-translate/core package.
</p>

## Installation

`yarn add @ngsm/i18n` or `npm i @ngsm/i18n --save`

## Usage

App module:
```ts
import { I18nModule } from '@ngsm/i18n';
...

@NgModule({
imports: [
...
// Option 1: module without paramaters
I18nModule,
// Option 2: module with parameters
// Add new langs to the list. Default language should be added as a first.
I18nModule.forRoot({
languages: ['en', 'pl']
}),
],
...
})
export class AppModule {}
```

Translations should be added in `i18n` directory in your assets (for example `/src/assets/i18n/en.json`):
```json
{
"homepage": {
"title": "My title"
}
}
```

In your HTML:
```html
{{ 'homepage.title' | translate }}
```

## Author

<table border="0">
<tr>
<td>
<a href="https://github.com/sebastianmusial" style="color: white">
<img src="https://github.com/sebastianmusial.png?s=150" width="150"/>
</a>
</td>
<td>
<p><strong>Sebastian Musiał</strong></p>
<p><img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQ4IDQ4IiBoZWlnaHQ9IjQ4cHgiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDQ4IDQ4IiB3aWR0aD0iNDhweCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGcgaWQ9IkV4cGFuZGVkIj48Zz48Zz48cGF0aCBkPSJNNDQsNDBINGMtMi4yMDYsMC00LTEuNzk0LTQtNFYxMmMwLTIuMjA2LDEuNzk0LTQsNC00aDQwYzIuMjA2LDAsNCwxLjc5NCw0LDR2MjRDNDgsMzguMjA2LDQ2LjIwNiw0MCw0NCw0MHogTTQsMTAgICAgIGMtMS4xMDMsMC0yLDAuODk3LTIsMnYyNGMwLDEuMTAzLDAuODk3LDIsMiwyaDQwYzEuMTAzLDAsMi0wLjg5NywyLTJWMTJjMC0xLjEwMy0wLjg5Ny0yLTItMkg0eiIvPjwvZz48Zz48cGF0aCBkPSJNMjQsMjkuMTkxTDYuNDU3LDE3Ljg0Yy0wLjQ2NC0wLjMwMS0wLjU5Ny0wLjkxOS0wLjI5Ny0xLjM4M3MwLjkxOS0wLjU5NiwxLjM4My0wLjI5N0wyNCwyNi44MDlMNDAuNDU3LDE2LjE2ICAgICBjMC40NjQtMC4yOTksMS4wODMtMC4xNjcsMS4zODMsMC4yOTdzMC4xNjcsMS4wODItMC4yOTcsMS4zODNMMjQsMjkuMTkxeiIvPjwvZz48Zz48cGF0aCBkPSJNNi4wMDEsMzRjLTAuMzIzLDAtMC42NDEtMC4xNTYtMC44MzMtMC40NDVjLTAuMzA3LTAuNDYtMC4xODMtMS4wOCwwLjI3Ny0xLjM4N2w5LTZjMC40Ni0wLjMwNywxLjA4MS0wLjE4MywxLjM4NywwLjI3NyAgICAgYzAuMzA3LDAuNDYsMC4xODMsMS4wOC0wLjI3NywxLjM4N2wtOSw2QzYuMzg0LDMzLjk0NSw2LjE5MSwzNCw2LjAwMSwzNHoiLz48L2c+PGc+PHBhdGggZD0iTTQxLjk5OSwzNGMtMC4xOSwwLTAuMzgzLTAuMDU1LTAuNTU0LTAuMTY4bC05LTZjLTAuNDYtMC4zMDctMC41ODQtMC45MjctMC4yNzctMS4zODcgICAgIGMwLjMwNi0wLjQ2LDAuOTI2LTAuNTg0LDEuMzg3LTAuMjc3bDksNmMwLjQ2LDAuMzA3LDAuNTg0LDAuOTI3LDAuMjc3LDEuMzg3QzQyLjY0LDMzLjg0NCw0Mi4zMjIsMzQsNDEuOTk5LDM0eiIvPjwvZz48L2c+PC9nPjwvc3ZnPg==" style="width: 18px; height: 18px; vertical-align: middle; margin: 0 5px 5px 0"> <a href="mailto:[email protected]">[email protected]</a></p>
<p><img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGhlaWdodD0iNTEycHgiIGlkPSLlvaLnirZfMl8xXyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTEyIDUxMjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTJweCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGcgaWQ9IuW9oueKtl8yIj48Zz48cGF0aCBkPSJNNDg1Ljk4LDExMy4xNDFjLTE2LjkyMyw3LjUwNi0zNS4xMDksMTIuNTc4LTU0LjE5NywxNC44NTggICAgYzE5LjQ4LTExLjY3OSwzNC40NDUtMzAuMTcxLDQxLjQ5LTUyLjIwOGMtMTguMjM0LDEwLjgxNC0zOC40MywxOC42NjgtNTkuOTI1LDIyLjg5OWMtMTcuMjEzLTE4LjM0MS00MS43MzgtMjkuNzk5LTY4Ljg4LTI5Ljc5OSAgICBjLTUyLjExNCwwLTk0LjM2OCw0Mi4yNS05NC4zNjgsOTQuMzY0YzAsNy4zOTYsMC44MzQsMTQuNTk4LDIuNDQ0LDIxLjUwNWMtNzguNDI3LTMuOTM2LTE0Ny45NjItNDEuNTA0LTE5NC41MDQtOTguNTk3ICAgIGMtOC4xMjMsMTMuOTM3LTEyLjc3NywzMC4xNDYtMTIuNzc3LDQ3LjQ0MWMwLDMyLjczOSwxNi42NTksNjEuNjIzLDQxLjk4LDc4LjU0NmMtMTUuNDY5LTAuNDkxLTMwLjAyLTQuNzM1LTQyLjc0Mi0xMS44MDQgICAgYy0wLjAwOSwwLjM5NS0wLjAwOSwwLjc4OC0wLjAwOSwxLjE4OGMwLDQ1LjcyMSwzMi41MjksODMuODU5LDc1LjY5OCw5Mi41MzFjLTcuOTE4LDIuMTU2LTE2LjI1NSwzLjMxMS0yNC44NjEsMy4zMTEgICAgYy02LjA4MSwwLTExLjk5Mi0wLjU5My0xNy43NTUtMS42OTNjMTIuMDA5LDM3LjQ4OCw0Ni44NTgsNjQuNzczLDg4LjE1Myw2NS41MzNjLTMyLjI5NiwyNS4zMTItNzIuOTg1LDQwLjM5Ni0xMTcuMTk4LDQwLjM5NiAgICBjLTcuNjE3LDAtMTUuMTI4LTAuNDQ2LTIyLjUxMS0xLjMyYzQxLjc2MiwyNi43NzUsOTEuMzY1LDQyLjQsMTQ0LjY1NSw0Mi40YzE3My41NzQsMCwyNjguNDkzLTE0My43OTQsMjY4LjQ5My0yNjguNDk2ICAgIGMwLTQuMDkxLTAuMDkyLTguMTYtMC4yNzMtMTIuMjA4QzQ1Ny4zMzIsMTQ4LjY4NCw0NzMuMzMsMTMyLjA2NCw0ODUuOTgsMTEzLjE0MXoiIHN0eWxlPSJmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiMyQ0E3RTA7Ii8+PC9nPjwvZz48L3N2Zz4=" style="width: 18px; height: 18px; vertical-align: middle; margin: 0 5px 5px 0"> <a href="https://twitter.com/SebaMusial">@sebamusial</a></p>
</td>
</tr>
</table>
41 changes: 41 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": 1,
"projects": {
"i18n": {
"projectType": "library",
"root": "",
"sourceRoot": "./src",
"prefix": "ngsm",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "./tsconfig.lib.json",
"project": "./ng-package.json"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"./tsconfig.lib.json",
"./tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!./**"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "./jest.config.js",
"tsConfig": "./tsconfig.spec.json",
"setupFile": "./src/test-setup.ts",
"passWithNoTests": true,
"codeCoverage": true
}
}
}
}
},
"defaultProject": "i18n"
}
16 changes: 16 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
name: 'i18n',
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
transform: {
'^.+\\.(ts|js|html)$': 'ts-jest'
},
resolver: '@nrwl/jest/plugins/resolver',
moduleFileExtensions: ['ts', 'js', 'html'],
coverageReporters: ['html'],
coverageDirectory: './coverage/i18n',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js'
]
};
11 changes: 11 additions & 0 deletions ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
"dest": "./dist/i18n",
"lib": {
"entryFile": "src/index.ts",
"umdModuleIds": {
"@ngx-translate/core": "@ngx-translate/core"
}
},
"whitelistedNonPeerDependencies": ["."]
}
44 changes: 44 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@ngsm/i18n",
"version": "0.1.1",
"private": false,
"dependencies": {
"@angular/common": "^9.1.0",
"@angular/compiler": "^9.1.4",
"@angular/core": "~9.1.0",
"@angular/platform-browser": "^9.1.4",
"@angular/platform-browser-dynamic": "~9.1.0",
"@angular/router": "^9.1.4",
"@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0",
"rxjs": "~6.5.4",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.901.0",
"@angular-devkit/build-ng-packagr": "~0.901.0",
"@angular/cli": "~9.1.0",
"@angular/compiler-cli": "~9.1.0",
"@types/jest": "25.1.4",
"@nrwl/jest": "9.2.3",
"ng-packagr": "^9.0.0",
"tsickle": "^0.38.1",
"jest": "25.2.4",
"jest-preset-angular": "8.1.3"
},
"scripts": {
"build": "ng build",
"test": "ng test",
"bump": "npm --no-git-tag-version version patch",
"release": "yarn build && cd dist/i18n && npm publish --access public"
},
"keywords": [
"Angular",
"JavaScript",
"RxJs",
"TypeScript",
"i18n",
"translate",
"ngx-translate"
]
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './lib/i18n.module';
export * from './lib/shared';
15 changes: 15 additions & 0 deletions src/lib/i18n.module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { async, TestBed } from '@angular/core/testing';

import { I18nModule } from './i18n.module';

describe('I18nModule', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [I18nModule]
}).compileComponents();
}));

it('should create', () => {
expect(I18nModule).toBeDefined();
});
});
42 changes: 42 additions & 0 deletions src/lib/i18n.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { HttpClient } from '@angular/common/http';
import { NgModule, ModuleWithProviders } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';

import { HttpLoaderFactory } from './shared/i18n.factory';
import { I18nService } from './shared/i18n.service';
import { LocalizationService } from './shared/localization.service';
import { I18nConfig } from './models/i18n.model';

@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
}),
],
exports: [TranslateModule],
providers: [
I18nService,
LocalizationService,
],
})
export class I18nModule {
static forRoot(config: I18nConfig): ModuleWithProviders {
return {
ngModule: I18nModule,
providers: [
{
provide: 'i18nConfig',
useValue: config,
}
]
};
}

constructor(public i18nService: I18nService) {}
}
19 changes: 19 additions & 0 deletions src/lib/models/i18n.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface I18nConfig {
languages: string[];
checkLocalication?: boolean;
}

export enum RtlLanguage {
far = 'far',
arc = 'arc',
ar = 'ar',
dv = 'dv',
ha = 'ha',
he = 'he',
khw = 'khw',
ks = 'ks',
ku = 'ku',
ps = 'ps',
ur = 'ur',
yi = 'yi',
}
18 changes: 18 additions & 0 deletions src/lib/shared/i18n-testing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { of } from 'rxjs';

import { TranslateLoader, TranslateModule } from '@ngx-translate/core';

const FAKE_TRANSLATIONS = { LOAD: 'This is a test' };

class FakeLoader implements TranslateLoader {
getTranslation() {
return of(FAKE_TRANSLATIONS);
}
}

export const I18nTestingModule = TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: FakeLoader,
},
});
6 changes: 6 additions & 0 deletions src/lib/shared/i18n.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
45 changes: 45 additions & 0 deletions src/lib/shared/i18n.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { TestBed } from '@angular/core/testing';

import { I18nService } from './i18n.service';
import { LocalizationService } from './localization.service';
import { I18nTestingModule } from './i18n-testing.module';

describe('Service: Language', () => {
let languageService: I18nService;

beforeEach(() =>
TestBed.configureTestingModule({
imports: [I18nTestingModule],
providers: [I18nService, LocalizationService],
}),
);

beforeEach(() => {
languageService = TestBed.inject(I18nService);
});

it('should be created', () => {
expect(I18nService).toBeTruthy();
expect(LocalizationService).toBeTruthy();
});

it('should set initial language', () => {
languageService.init();
expect(localStorage.getItem('lang')).toBeTruthy();
});

it('should set language', () => {
languageService.setLanguage('en');
expect(localStorage.getItem('lang')).toBe('en');
});

it('should set value in localStorage', () => {
languageService.setLanguageInLocalStorage('en');
expect(localStorage.getItem('lang')).toBe('en');
});

it('should get value from localStorage', () => {
localStorage.setItem('lang', 'en');
expect(languageService.getLanguageFromLocalStorage()).toBe('en');
});
});
Loading

0 comments on commit a6d823d

Please sign in to comment.