Removed ng-translate code from the core

Added ng-translate dependency
This commit is contained in:
mauriziovitale84 2016-05-23 17:32:01 +01:00
parent 3f28925d35
commit 339b84f042
17 changed files with 44 additions and 526 deletions

View File

@ -53,6 +53,7 @@
"ng2-alfresco-login": "^0.1.0",
"ng2-alfresco-search": "^0.1.2",
"ng2-alfresco-upload": "^0.1.0",
"ng2-translate": "^1.11.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",
"systemjs": "0.19.26",

View File

@ -25,7 +25,8 @@
'ng2-alfresco-login': 'node_modules/ng2-alfresco-login',
'ng2-alfresco-search': 'node_modules/ng2-alfresco-search',
'ng2-alfresco-upload': 'node_modules/ng2-alfresco-upload',
'rxjs': 'node_modules/rxjs'
'rxjs': 'node_modules/rxjs',
'ng2-translate': 'node_modules/ng2-translate'
};
// packages tells the System loader how to load when no filename and/or no extension
@ -40,6 +41,7 @@
'ng2-alfresco-login': {defaultExtension: 'js'},
'ng2-alfresco-search': {defaultExtension: 'js'},
'ng2-alfresco-upload': {defaultExtension: 'js'},
'ng2-translate': {defaultExtension: 'js'},
'rxjs': {defaultExtension: 'js'}
};

View File

@ -1,7 +1,7 @@
{
"name": "ng2-alfresco-core",
"description": "Alfresco Angular 2 Components core",
"version": "0.1.19",
"version": "0.1.20",
"author": "Alfresco Software, Ltd.",
"scripts": {
"typings": "typings install",
@ -53,7 +53,8 @@
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",
"systemjs": "0.19.26",
"zone.js": "^0.6.12"
"zone.js": "^0.6.12",
"ng2-translate": "^1.11.3"
},
"peerDependencies": {
"angular2": "2.0.0-beta.15"

View File

@ -15,152 +15,18 @@
* limitations under the License.
*/
import { PipeTransform, Pipe, Injectable, EventEmitter, OnDestroy, ChangeDetectorRef } from 'angular2/core';
import { AlfrescoTranslationService, LangChangeEvent } from './AlfrescoTranslationService.service';
import { isPresent, isArray } from 'angular2/src/facade/lang';
import { Injectable, ChangeDetectorRef, Pipe } from 'angular2/core';
import { TranslatePipe } from 'ng2-translate/ng2-translate';
import { AlfrescoTranslationService } from './AlfrescoTranslationService.service';
@Injectable()
@Pipe({
name: 'translate',
pure: false // required to update the value when the promise is resolved
})
export class AlfrescoPipeTranslate implements PipeTransform, OnDestroy {
value: string = '';
lastKey: string;
lastParams: any[];
onLangChange: EventEmitter<LangChangeEvent>;
export class AlfrescoPipeTranslate extends TranslatePipe {
constructor(private translate: AlfrescoTranslationService, private _ref: ChangeDetectorRef) {
}
/**
* @name equals
*
* @description
* Determines if two objects or two values are equivalent.
*
* Two objects or values are considered equivalent if at least one of the following is true:
*
* * Both objects or values pass `===` comparison.
* * Both objects or values are of the same type and all of their properties are equal by
* comparing them with `equals`.
*
* @param {*} o1 Object or value to compare.
* @param {*} o2 Object or value to compare.
* @returns {boolean} True if arguments are equal.
*/
private equals(o1: any, o2: any): boolean {
if (o1 === o2) {
return true;
}
if (o1 === null || o2 === null) {
return false;
}
if (o1 !== o1 && o2 !== o2) {
return true;
} // NaN === NaN
let t1 = typeof o1, t2 = typeof o2, length: number, key: any, keySet: any;
if (t1 === t2 && t1 === 'object') {
if (isArray(o1)) {
if (!isArray(o2)) {
return false;
}
length = o1.length;
if (length === o2.length) {
for (key = 0; key < length; key++) {
if (!this.equals(o1[key], o2[key])) {
return false;
}
}
return true;
}
} else {
if (isArray(o2)) {
return false;
}
keySet = Object.create(null);
for (key in o1) {
if (key) {
if (!this.equals(o1[key], o2[key])) {
return false;
}
keySet[key] = true;
}
}
for (key in o2) {
if (!(key in keySet) && typeof o2[key] !== 'undefined') {
return false;
}
}
return true;
}
}
return false;
}
updateValue(key: string, interpolateParams?: Object): void {
this.translate.get(key, interpolateParams).subscribe((res: string) => {
this.value = res ? res : key;
this._ref.markForCheck();
});
}
transform(query: string, ...args: any[]): any {
if (!query || query.length === 0) {
return query;
}
// if we ask another time for the same key, return the last value
if (this.equals(query, this.lastKey) && this.equals(args, this.lastParams)) {
return this.value;
}
let interpolateParams: Object;
if (args.length && args[0] !== null) {
if (typeof args[0] === 'string' && args[0].length) {
// we accept objects written in the template such as {n:1},
// which is why we might need to change it to real JSON objects such as {"n":1}
try {
interpolateParams = JSON.parse(args[0].replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": '));
} catch (e) {
throw new SyntaxError(`Wrong parameter in TranslatePipe. Expected a valid Object, received: ${args[0]}`);
}
} else if (typeof args[0] === 'object' && !Array.isArray(args[0])) {
interpolateParams = args[0];
}
}
// store the query, in case it changes
this.lastKey = query;
// store the params, in case they change
this.lastParams = args;
// set the value
this.updateValue(query, interpolateParams);
// if there is a subscription to onLangChange, clean it
this._dispose();
// subscribe to onLangChange event, in case the language changes
this.onLangChange = this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
this.updateValue(query, interpolateParams);
});
return this.value;
}
/**
* Clean any existing subscription to onLangChange events
* @private
*/
_dispose(): void {
if (isPresent(this.onLangChange)) {
this.onLangChange.unsubscribe();
this.onLangChange = undefined;
}
}
ngOnDestroy(): void {
this._dispose();
constructor(translate: AlfrescoTranslationService, _ref: ChangeDetectorRef) {
super(translate, _ref);
}
}

View File

@ -18,7 +18,7 @@
import { Injectable } from 'angular2/core';
import { Response, Http } from 'angular2/http';
import { Observable } from 'rxjs/Observable';
import { TranslateLoader } from './AlfrescoTranslationService.service';
import { TranslateLoader } from 'ng2-translate/ng2-translate';
@Injectable()
export class AlfrescoTranslationLoader implements TranslateLoader {

View File

@ -15,87 +15,18 @@
* limitations under the License.
*/
import { Injectable, Optional, EventEmitter } from 'angular2/core';
import { Injectable, Optional } from 'angular2/core';
import { Http } from 'angular2/http';
import { MissingTranslationHandler, TranslateService } from 'ng2-translate/ng2-translate';
import { AlfrescoTranslationLoader } from './AlfrescoTranslationLoader.service';
import { Http, Response } from 'angular2/http';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/merge';
import 'rxjs/add/operator/toArray';
import { Parser } from './translate.parser';
export interface LangChangeEvent {
lang: string;
translations: any;
}
export abstract class MissingTranslationHandler {
/**
* A function that handles missing translations.
* @param key the missing key
* @returns {any} a value or an observable
* If it returns a value, then this value is used.
* If it return an observable, the value returned by this observable will be used (except if the method was "instant").
* If it doesn't return then the key will be used as a value
*/
abstract handle(key: string): any;
}
export abstract class TranslateLoader {
abstract getTranslation(lang: string): Observable<any>;
}
export class TranslateStaticLoader implements TranslateLoader {
constructor(private http: Http, private prefix: string = 'i18n', private suffix: string = '.json') {
}
/**
* Gets the translations from the server
* @param lang
* @returns {any}
*/
public getTranslation(lang: string): Observable<any> {
return this.http.get(`${this.prefix}/${lang}${this.suffix}`)
.map((res: Response) => res.json());
}
}
@Injectable()
export class AlfrescoTranslationService {
/**
* The lang currently used
*/
public currentLang: string = this.defaultLang;
export class AlfrescoTranslationService extends TranslateService {
userLang: string = 'en' ;
currentLoader: AlfrescoTranslationLoader;
/**
* An EventEmitter to listen to lang changes events
* onLangChange.subscribe((params: LangChangeEvent) => {
* // do something
* });
* @type {ng.EventEmitter<LangChangeEvent>}
*/
public onLangChange: EventEmitter<LangChangeEvent> = new EventEmitter<LangChangeEvent>();
private pending: any;
private translations: any = {};
private defaultLang: string;
private langs: Array<string>;
private parser: Parser = new Parser();
userLang: string = 'en';
/**
*
* @param http The Angular 2 http provider
* @param currentLoader An instance of the loader currently used
* @param missingTranslationHandler A handler for missing translations.
*/
constructor(private http: Http, public currentLoader: AlfrescoTranslationLoader, @Optional()
private missingTranslationHandler: MissingTranslationHandler) {
constructor(http: Http, currentLoader: AlfrescoTranslationLoader, @Optional() missingTranslationHandler: MissingTranslationHandler) {
super(http, currentLoader, missingTranslationHandler);
}
translationInit(name: string = ''): void {
@ -113,238 +44,4 @@ export class AlfrescoTranslationService {
this.getTranslation(this.userLang);
}
}
/**
* Sets the default language to use as a fallback
* @param lang
*/
public setDefaultLang(lang: string): void {
this.defaultLang = lang;
}
/**
* Changes the lang currently used
* @param lang
* @returns {Observable<*>}
*/
public use(lang: string): Observable<any> {
let pending: Observable<any>;
// check if this language is available
if (typeof this.translations[lang] === 'undefined') {
// not available, ask for it
pending = this.getTranslation(lang);
}
if (typeof pending !== 'undefined') {
pending.subscribe((res: any) => {
this.changeLang(lang);
});
return pending;
} else { // we have this language, return an Observable
this.changeLang(lang);
return Observable.of(this.translations[lang]);
}
}
/**
* Gets an object of translations for a given language with the current loader
* @param lang
* @returns {Observable<*>}
*/
public getTranslation(lang: string): Observable<any> {
this.pending = this.currentLoader.getTranslation(lang).share();
this.pending.subscribe((res: Object) => {
this.translations[lang] = res;
this.updateLangs();
}, (err: any) => {
throw err;
}, () => {
this.pending = undefined;
});
return this.pending;
}
/**
* Manually sets an object of translations for a given language
* @param lang
* @param translations
*/
public setTranslation(lang: string, translations: Object): void {
this.translations[lang] = translations;
this.updateLangs();
}
/**
* Returns an array of currently available langs
* @returns {any}
*/
public getLangs(): Array<string> {
return this.langs;
}
/**
* Update the list of available langs
*/
private updateLangs(): void {
this.langs = Object.keys(this.translations);
}
/**
* Returns the parsed result of the translations
* @param translations
* @param key
* @param interpolateParams
* @returns {any}
*/
private getParsedResult(translations: any, key: any, interpolateParams?: Object): any {
let res: string|Observable<string>;
if (key instanceof Array) {
let result: any = {},
observables: boolean = false;
for (let k of key) {
result[k] = this.getParsedResult(translations, k, interpolateParams);
if (typeof result[k].subscribe === 'function') {
observables = true;
}
}
if (observables) {
let mergedObs: any;
for (let k of key) {
let obs = typeof result[k].subscribe === 'function' ? result[k] : Observable.of(result[k]);
if (typeof mergedObs === 'undefined') {
mergedObs = obs;
} else {
mergedObs = mergedObs.merge(obs);
}
}
return mergedObs.toArray().map((arr: Array<string>) => {
let obj: any = {};
arr.forEach((value: string, index: number) => {
obj[key[index]] = value;
});
return obj;
});
}
return result;
}
if (translations) {
res = this.parser.interpolate(this.parser.getValue(translations, key), interpolateParams);
}
if (typeof res === 'undefined' && this.defaultLang && this.defaultLang !== this.currentLang) {
res = this.parser.interpolate(this.parser.getValue(this.translations[this.defaultLang], key), interpolateParams);
}
if (!res && this.missingTranslationHandler) {
res = this.missingTranslationHandler.handle(key);
}
return res || key;
}
/**
* Gets the translated value of a key (or an array of keys)
* @param key
* @param interpolateParams
* @returns {any} the translated key, or an object of translated keys
*/
public get(key: string|Array<string>, interpolateParams?: Object): Observable<string|any> {
if (!key) {
throw new Error('Parameter "key" required');
}
// check if we are loading a new translation to use
if (this.pending) {
return Observable.create((observer: Observer<string>) => {
let onComplete = (res: string) => {
observer.next(res);
observer.complete();
};
this.pending.subscribe((resSub: any) => {
let res = this.getParsedResult(resSub, key, interpolateParams);
if (typeof res.subscribe === 'function') {
res.subscribe(onComplete);
} else {
onComplete(res);
}
});
});
} else {
let res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
if (typeof res.subscribe === 'function') {
return res;
} else {
return Observable.of(res);
}
}
}
/**
* Returns a translation instantly from the internal state of loaded translation.
* All rules regarding the current language, the preferred language of even fallback languages will be used except any promise handling.
* @param key
* @param interpolateParams
* @returns {string}
*/
public instant(key: string|Array<string>, interpolateParams?: Object): string|any {
if (!key) {
throw new Error('Parameter "key" required');
}
let res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
if (typeof res.subscribe !== 'undefined') {
if (key instanceof Array) {
let obj: any = {};
key.forEach((value: string, index: number) => {
obj[key[index]] = key[index];
});
return obj;
}
return key;
} else {
return res;
}
}
/**
* Sets the translated value of a key
* @param key
* @param value
* @param lang
*/
public set(key: string, value: string, lang: string = this.currentLang): void {
this.translations[lang][key] = value;
this.updateLangs();
}
/**
* Changes the current lang
* @param lang
*/
private changeLang(lang: string): void {
this.currentLang = lang;
this.onLangChange.emit({lang: lang, translations: this.translations[lang]});
}
/**
* Allows to reload the lang file from the file
* @param lang
* @returns {Observable<any>}
*/
public reloadLang(lang: string): Observable<any> {
this.resetLang(lang);
return this.getTranslation(lang);
}
/**
* Deletes inner translation
* @param lang
*/
public resetLang(lang: string): void {
this.translations[lang] = undefined;
}
}

View File

@ -1,65 +0,0 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class Parser {
templateMatcher: RegExp = /{{\s?([^{}\s]*)\s?}}/g;
/**
* Interpolates a string to replace parameters
* "This is a {{ key }}" ==> "This is a value", with params = { key: "value" }
* @param expr
* @param params
* @returns {string}
*/
public interpolate(expr: string, params?: any): string {
if (typeof expr !== 'string' || !params) {
return expr;
}
return expr.replace(this.templateMatcher, (substring: string, b: string) => {
let r = this.getValue(params, b);
return typeof r !== 'undefined' ? r : substring;
});
}
/**
* Gets a value from an object by composed key
* parser.getValue({ key1: { keyA: 'valueI' }}, 'key1.keyA') ==> 'valueI'
* @param target
* @param key
* @returns {string}
*/
public getValue(target: any, key: string): string {
let keys = key.split('.');
key = '';
do {
key += keys.shift();
if (target[key] !== undefined && (typeof target[key] === 'object' || !keys.length)) {
target = target[key];
key = '';
} else if (!keys.length) {
target = undefined;
} else {
key += '.';
}
} while (keys.length);
return target;
}
}

View File

@ -26,6 +26,7 @@
'ng2-translate': 'node_modules/ng2-translate',
'rxjs': 'node_modules/rxjs',
'angular2' : 'node_modules/angular2',
'ng2-translate' : 'node_modules/ng2-translate',
'app': 'dist/src'
},
packages: {

View File

@ -17,6 +17,7 @@
"es6-promise": "3.0.2",
"es6-shim": "0.35.0",
"ng2-alfresco-login": "^0.1.0",
"ng2-translate": "^1.11.3",
"ng2-translate": "^1.11.2",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",

View File

@ -17,13 +17,17 @@ System.config({
'ng2-alfresco-core/dist': {
defaultExtension: 'js'
},
'ng2-translate': {
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
}
},
map: {
'ng2-alfresco-core/dist': '/base/node_modules/ng2-alfresco-core/dist',
'rxjs': '/base/node_modules/rxjs'
'rxjs': '/base/node_modules/rxjs',
'ng2-translate' : '/base/node_modules/ng2-translate'
}
});

View File

@ -18,6 +18,7 @@ module.exports = function (config) {
{pattern: 'node_modules/angular2/bundles/router.dev.js', included: true, watched: false},
{pattern: 'node_modules/alfresco-core-rest-api/bundle.js', included: true, watched: false},
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
{pattern: 'karma-test-shim.js', included: true, watched: true},

View File

@ -1,7 +1,7 @@
{
"name": "ng2-alfresco-login",
"description": "Alfresco Angular2 Login Component",
"version": "0.1.6",
"version": "0.1.7",
"author": "Alfresco Software, Ltd.",
"scripts": {
"typings": "typings install",
@ -63,7 +63,8 @@
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",
"systemjs": "0.19.26",
"zone.js": "^0.6.12"
"zone.js": "^0.6.12",
"ng2-translate": "^1.11.3"
},
"peerDependencies": {
"angular2": "2.0.0-beta.15"

View File

@ -31,6 +31,7 @@
'ng2-alfresco-upload': 'node_modules/ng2-alfresco-upload',
'rxjs': 'node_modules/rxjs',
'angular2' : 'node_modules/angular2',
'ng2-translate' : 'node_modules/ng2-translate',
'app': 'dist/src'
},
packages: {

View File

@ -21,6 +21,7 @@
"material-design-lite": "^1.1.3",
"ng2-alfresco-core": "^0.1.6",
"ng2-alfresco-upload": "^0.1.0",
"ng2-translate": "^1.11.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",
"zone.js": "0.6.6"

View File

@ -17,13 +17,17 @@ System.config({
'ng2-alfresco-core/dist': {
defaultExtension: 'js'
},
'ng2-translate': {
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
}
},
map: {
'ng2-alfresco-core/dist': '/base/node_modules/ng2-alfresco-core/dist',
'rxjs': '/base/node_modules/rxjs'
'rxjs': '/base/node_modules/rxjs',
'ng2-translate' : '/base/node_modules/ng2-translate'
}
});

View File

@ -18,6 +18,7 @@ module.exports = function (config) {
{pattern: 'node_modules/angular2/bundles/router.dev.js', included: true, watched: false},
{pattern: 'node_modules/alfresco-core-rest-api/bundle.js', included: true, watched: false},
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false},
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
{pattern: 'karma-test-shim.js', included: true, watched: true},

View File

@ -1,7 +1,7 @@
{
"name": "ng2-alfresco-upload",
"description": "Alfresco Angular2 Upload Component",
"version": "0.1.9",
"version": "0.1.10",
"author": "Alfresco Software, Ltd.",
"scripts": {
"typings": "typings install",
@ -55,7 +55,8 @@
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2",
"systemjs": "0.19.26",
"zone.js": "^0.6.12"
"zone.js": "^0.6.12",
"ng2-translate": "^1.11.3"
},
"peerDependencies": {
"angular2": "2.0.0-beta.15"