è¯ãäžæ¥ã
è¿ãå°æ¥ãngx-translateã©ã€ãããã¯ãå
¬éããäºå®ã§ãã
- æåã®éšåã§ã¯ãJSONãã¡ã€ã«å
ã§ãã€ããã³ã³ãã€ã«ããæ¹æ³ãæããããã«
Translateompiler
ãæ€èšŒããŸãã - 2çªç®ã®éšåã§ã¯ã
TranslateLoader
ã眮ãæããããã«TranslateHttpLoader
ãäœæããŸãïŒããã¯ngx-translateããã¯ã¹ããåºãŸããããããã§ãåå¥ã«ã€ã³ã¹ããŒã«ã§ããããã©ã«ãã®ããŒããŒã§ãïŒã
TranslateLoader
ã¯ããŸããã©ãŠã¶ãŒèšèªã«æ³šæãæãããã©ãŒã«ããã¯ããžãã¯ãå«ã¿ãMomentJsããŒã«ãªãŒãŒã·ã§ã³ãã€ã³ããŒãããAPP_INITIALIZERãä»ããŠããŒããAPP_INITIALIZER
ã
ãŸããngx-translate json`ovãã¢ããªã±ãŒã·ã§ã³ã«ããŒãããæåã®æ¹æ³ãæ€èšããŠãã ããã 3çªç®ã®éšåã¯å®éšçã§ãWebpackãŠãŒã¶ãŒã®ã©ã€ãããã¯ã§ãã ãããžã§ã¯ãã®ngx-translateã€ã³ãã©ã¹ãã©ã¯ãã£ãæ¹åããtranslate jsonããã³ãã«ã§æ§ç¯ããæ¹æ³ãæ€èšããŸãã
å§ããŸãããã
ãããã£ãŠãã€ã³ã¿ãŒãã§ãŒã¹ã«ãšã³ãã£ãã£ã®äœææ¥ã远å ã®ããã¹ããšãšãã«è¡šç€ºããå¿
èŠããããšããŸãããã
<p>This entity created at 15:47 01-02-2003 by Some Guy</p>
ãã®è¡ã®en.jsonã«æ°ãããã£ãŒã«ãã远å ããŸãã
"ENTITY_CREATED_AT": "This entity created at {{createdAtDate}} by {{guyName}}"
ã³ã³ããŒãã³ãã®ãã¥ãŒã§ã¯ãåœç¶ãtranslateãã£ã¬ã¯ãã£ããŸãã¯pipeã远å ããŸã
<div translate="ENTITY_CREATED_AT" [translateParams]="{createdAtDate: entity.createdAt, guyName: entity.name}"></div>
ãããããã®ã¢ãããŒãã§ã¯åé¡ãçºçããŸã-createdAtDateãã£ãŒã«ãã¯æ¢ã«ããŒã«ã©ã€ãºãããŠããå¿
èŠããããããã§ãªãå Žåã¯new Date().toString().
ã®çµæã衚瀺ããnew Date().toString().
ãã®åé¡ã«ã¯2aã®è§£æ±ºçããããŸãã
ããã€ãã®ãã¹ããã©ã¯ãã£ã¹ïŒç§ã¯translateParamsã®å¥ã®ãªããžã§ã¯ãã転éããŠãjsonã®ãã£ãŒã«ããå®éã®ã¢ãã«ã®ãã£ãŒã«ãã«é
眮ããããšã奜ã¿ãŸãã
ãããã·ã¥ïŒ
//our Entity model class Entity { createdAt: Date; name: string; someComplexField: ComplexType; } //inside some HTML [translateParams]="{createdAtDate: entity.createdAt, guyName: entity.name}" // separate object
ãã¡ãããjsonã§ã¯ããšã³ãã£ãã£ã¢ãã«ã§ãã£ãŒã«ãåãæç€ºçã«æå®ããããšã§ãå®éã®ã¢ãã«ã®ãã£ãŒã«ããåç
§ããããšãã§ããŸããã
"ENTITY_CREATED_AT": "This entity created at {{createdAt}} by {{name}}" // entity.createdAt, entity.name
translateParamsã§ã¯ãåã«ãšã³ãã£ãã£ãæž¡ããŸãã
<div translate="ENTITY_CREATED_AT" [translateParams]="entity"></div>
ãããããã§ã«10ã®èšèªããµããŒãããŠãããã¢ãã«ãngx-translateã«é¢é£ä»ããããŠãããã£ãŒã«ãã®1ã€ã®ååãçªç¶å€æŽããå Žåã¯ã©ããªããŸããïŒ
ãã¥ãŒã³ã³ããŒãã³ãå
ã®ãã«ãæ©èœã
ãã¥ãŒã³ã³ããŒãã³ãå
ã«é¢æ°ãäœæããtranslateParamsã«è»¢éããããã®æ¢è£œã®ãªããžã§ã¯ããè¿ããŸãã
public getEntityTranslateParam(dateFormat: string) { return { createdAtDate: moment.format(dateFormat, entity.createdAt),
æ¬ ç¹ããããŸã-ãã®ãããªæ©èœã§åã³ã³ããŒãã³ããè©°ãŸãããå¿
èŠããããŸãã ãã¡ããããã®ãããªãªããžã§ã¯ããäœæããç¹å®ã®ãµãŒãã¹ã远å ããŠãã³ã³ããŒãã³ãã®ã³ãŒããå°ããããã«ããããšãã§ããŸãããã®ãµãŒãã¹ã¯ã©ãã«ã§ã泚å
¥ããå¿
èŠãããããããªããžã§ã¯ããååã«å€§ããå Žåã«ã®ã¿æå³ããããŸãã
ENTITY_CREATED_ATã2ã€ã®éšåã«åããŸãã
"ENTITY_CREATED_AT_1": "This entity created at", "ENTITY_CREATED_AT_2": "by {{guyName}}"
ããã§ç§ãã¡ã¯æé·ããHTMLãèªãããšãé£ãããªã£ãŠããŸãããä»ã§ã¯ããããçš®é¡ã®ãã€ãã䜿çšã§ããŸãïŒ ïŒãã¡ããããã€ããã±ãŒã·ã§ã³ãã£ã¬ã¯ãã£ãã䜿çšã§ããŸãããdivå
ã«ããã«htmlãäœæããå¿
èŠããããŸãïŒ
<div> {{'ENTITY_CREATED_AT_1' | translate}} {{entity.createdAt | dateFormatPipe:LL}} {{'ENTITY_CREATED_AT_2' | translate:{guyName:entity.guyName} }} </div>
åªããã€ã³ãã©ã¹ãã©ã¯ãã£ã«ã€ããŠãngx-translateéçºè
ãç§°è³ããŠãã ããïŒ
ngx-translateã¢ãžã¥ãŒã«ãã¢ããªã±ãŒã·ã§ã³ã«ã€ã³ããŒããããšããã«ã¹ã¿ã Translateompiler
ãæäŸã§ããŸãã
ãšããã§ãããã«åªããè€æ°ã®\æ§å¥ãªã©ãžã®ãªã³ã¯ããããŸãã ngx-translateã§åäœããã³ã³ãã€ã©ã
ç§ãã¡ã®ã¿ã¹ã¯ã¯ãngx-translateããŒã«ã©ã€ãºå
ã§ãã€ããå®è¡ã§ããTranslateompilerãäœæããããšã§ãã
ãŸããDIãæºåãïŒInjector`aãããã€ããååŸããããïŒãngx-translateãåæåããããšããå§ããŸãããã
ã¢ãžã¥ãŒã«ã®ãããã€ããŒã«ç®çã®ãã€ãã远å ããŸããç§ã®å Žåãã¢ããªã±ãŒã·ã§ã³ã«ã¯è€æ°ã®ã¢ãžã¥ãŒã«ãå«ãŸããŠãããããããã¯SharedModule
ã§ãã
@NgModule({ // imports: [ ...exportedModules ], declarations: [ ...exportedDeclarations ], exports: [ ...exportedModules, ...exportedDeclarations ], providers: [ // declare pipes available with injector [ DateFormatPipe, {provide: 'dateFormat', useExisting: DateFormatPipe} ] ] }) export class SharedModule { }
ngx-translateãåæåãã CustomTranslateCompiler
ããã€ã³ãããŸãã
ç§ã®å Žåã CoreModule
ã䜿çšããŠãCoreModule
ã
import { CustomTranslateCompiler } from 'app/_core/services/translate/translate.compiler'; @NgModule({ // some needed providers imports: [ CommonModule, TranslateModule.forRoot({ compiler: { provide: TranslateCompiler, useClass: CustomTranslateCompiler, deps: [Injector] }, }) ], exports: [CommonModule, TranslateModule] }) export class CoreModule { }
ã¢ãžã¥ãŒã«ã®ãããã€ããŒã§å®£èšãããŠãããã€ãã®ã¿ã䜿çšã§ããŸãïŒãã€ãã®äŸ-dateFormstïŒã
"ENTITY_CREATED_AT": "This entity created at {{createdAtDate | dateFormat:LL}} by {{guyName}}"
ããã©ã«ãã§PipeTranslateCompiler
å®çŸ©ããŸãããã
export class PipeTranslateCompiler implements TranslateCompiler { constructor(private injector: Injector, private errorHandler: ErrorHandler) { } public compile(value: string, lang: string): string | Function { return value; } public compileTranslations(translations: any, lang: string): any { return translations; } }
2ã€ã®æ©èœããããŸãã
compileTranslations-å
¥åæã«ããŒããããjsonãååŸããŸãïŒTranslateHttpLoaderããããŠã³ããŒãã§ããŸãïŒã
compile-1ã€ã®å€ã®ã¿ãååŸãã TranslateService.set('some translate val', 'key', 'en')
ä»ããŠngx-translateã«æç€ºçã«ãã£ãŒã«ãã远å ãããšåŒã³åºãããŸãã
ååã«å€§ããjsonã¯compileTranslationsã«å
¥ãå¯èœæ§ãããããããªããžã§ã¯ãå
šäœã®ãã£ãŒã«ããååž°çã«èª¿ã¹ãŠåå€ãè§£æããå¿
èŠããããŸããã©ã®ãã£ãŒã«ããè§£æããã©ã®ãã£ãŒã«ããè§£æããªãããäºåã«ç¥ãããã§ãã ãããã£ãŠãPipeTranslateCompilerã§ä¿åããå¿
èŠããããã¹ãŠã®ãã£ãŒã«ãã@ã§ããŒã¯ããããšã«ããŸããã
"@ENTITY_CREATED_AT": "This entity created at {{createdAtDate | dateFormat:LL}} by {{guyName}}", // "OTHER_KEY": "This is regular entity" //
ã§ã¯ã compile - string | Function
æ»ãå€ã®åã«æ³šæããŸãããcompile - string | Function
compile - string | Function
ãããã¯ãä»»æã®æååå€ã颿°ã«å€æã§ããããšãæå³ããŸã.HTMLãã¥ãŒã§ngx-translateã®å€æãã€ããŸãã¯ãã£ã¬ã¯ãã£ãã䜿çšãããšã颿°ãäœããã®ããŒã«é
眮ãããŠããå Žåããã©ã¡ãŒã¿ãŒã§åŒã³åºããŸãã translateParamsã«æž¡ããŸãã
<div>{{'ENTITY_CREATED_AT' | translate:paramsObject}}</div>
ãã®ããã "This entity created at {{createdAtDate | dateFormat:LL}} by {{guyName}}"
ãšããæååãè§£æãã颿°ã§çœ®ãæããå¿
èŠããããŸãã
æåã«ãæååã®è§£æçµæãä¿åããæ¹æ³ãæ³åããŠã¿ãŸããããããã«ãããåŸã§ãã©ã¡ãŒã¿ãŒã«åºã¥ããŠãæ¢ã«é©çšããããã€ããå«ãæååããã°ããååŸã§ããŸãã
2+åã®ãã©ã¡ãŒã¿ãŒãæã€2+åã®ãã€ããããã«è§£æã§ããããã«ããã
"SOME_KEY": "value1: {{dateField | dateFormat:LL}} and value2: {{anotherField | customPipe:param1:param2}}
ãã®ãããæ¬åŒ§{{ã*}}å
ã®éšåã匷調衚瀺ããŠãæååãæ£èŠè¡šçŸã§è§£æããå¿
èŠããããŸãã
匷調衚瀺ããããã©ã±ããããšã«ãå
éšã®å
容ããã€ãã®ååããã€ããã©ã¡ãŒã¿ãŒã®é
åããªããžã§ã¯ããã£ãŒã«ãã®ååã«é¢ããæ
å ±ãå¿
èŠã§ãã
{{__ | _:1:2}}
䟿å®äžãããã€ãã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ããŸãããã
interface PipedObject { property: string;
è§£æé¢æ°ïŒ
private parseTranslation(res: string): {pipedObjects: PipedObject[], matches: string[]} { // "{{dateField | dateFormat:LL | additionalPipe:param1}}", "{{anotherField | customPipe:param1:param2}}" let matches = res.match(/{{.[^{{]*}}/g); let pipedObjects: PipedObject[] = []; (matches || []).forEach((v) => { // {{dateField | dateFormat:LL}} -> dateField|dateFormat:LL|additionalPipe:param1 v = v.replace(/[{}\s]+/g, ''); // : dateField|dateFormat:LL|additionalPipe:param1 let pipes = v.split('|'); let objectPropertyName = pipes[0]; // dateField pipes = pipes.slice(1); // [dateFormat:LL, additionalPipe:param1] for(let pipe of pipes) { // customPipe:param1:param2 -> ['customPipe', 'param1', 'param2'] let pipeTokens = pipe.split(':'); pipedObjects.push({ property: objectPropertyName, pipe: { name: pipeTokens[0], // customPipe params: pipeTokens.slice(1) // ['param1', 'param2'] } }); } }); return {pipedObjects, matches}; }
ããŠããŸãã¯ãparseTranslationãšã1ã€ã®å€ã®ã¿ãã³ã³ãã€ã«ãã颿°ããã€ã³ãããŸã-compile
public compile(value: string, lang: string): string | Function { return this.compileValue(value); } private compileValue(val): Function { let parsedTranslation = this.parseTranslation(val); // , return (argsObj: object) => { // - ngx-translate // : value1: {{dateField | dateFormat:LL}} and value2: {{anotherField | customPipe:param1:param2}} let res = val; parsedTranslation.pipedObjects.forEach((o, i) => { // DI , . const pipe = this.injector.get(o.pipe.name); const property = argsObj[o.property]; // argsObj - - [translateParams] // pipe.transform(prop, o.pipe.params); const pipeParams = this.assignPipeParams(argsObj, o.pipe.params || []); if(!property) { return res; } let pipedValue = pipe.transform( property, pipeParams.length === 1 ? pipeParams[0] : pipeParams ); // {{*.}} . {{dateField | dateFormat:LL}} -> 15:00 res = res.replace(parsedTranslation.matches[i], pipedValue); }); return res; }; } private assignPipeParams(obj: object, params: string[]) { let assignedParams = []; params.forEach(p => { if(obj.hasOwnProperty(p)) { assignedParams.push(obj[p]); } else { assignedParams.push(p); } }); return assignedParams; }
æç¢ºã«ããããã«ãassignPipeParamsã䜿çšãããšãã³ã³ããŒãã³ãããcustomPipeã«ãã©ã¡ãŒã¿ãŒãæž¡ãããšãã§ããŸãã
"@SOME": "value1: {{dateField | dateFormat:LL}} and value2: {{anotherField | customPipe:param1}} // :LL :param1 - <div>{{'@SOME' | myTranslate:{dateField: entity.value1, anotherField: entity.value2, param1: 'DYNAMIC_VALUE'} }}</div> // :param1
compileTranslationsãããã¹ãŠã®jsonãè§£æããæ¹æ³ã«ã€ããŠã¯èª¬æããŸãããã¹ã¿ãã¯ãªãŒããŒãããŒã§ã¯ãjsonæ§é å
šäœããã©ããŒã¹ããããã®å€ãã®ã¡ãœãããèŠã€ããããšãã§ããŸãã
public compileTranslations(translations: any, lang: string): any { this.iterateTranslations(translations); return translations; } private iterateTranslations(obj) { for (let key in obj) { if (obj.hasOwnProperty(key)) { const val = obj[key]; const isString = typeof val === 'string'; if(key[0] === '@' && isString) { obj[key] = this.compileValue(val);
ã§ããïŒ ngx-translate jsonå
ã§ãã€ãã䜿çšã§ããããã«ãªããŸããïŒ
æ°ãã䟿å©ãªAngular 6æ©èœããã§ã¯ãAngular Elementsãšã¯äœããç°¡åã«ãæ¬è³ªçã«èŠãããšãã§ããŸãã
ãããªããã®ãœãŒã¹ããããŸã
äžè¬ã«ãAngular Elementsã¯ãŸã å®éšçã§ãããããAngularããWebã³ã³ããŒãã³ããã³ã³ãã€ã«ããŠJavaScriptã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããããšã¯ã§ããŸããã
ãããïŒ ãããããã®å©ç¹ã¯ãã§ã«ãããŸãã ããã§ãAngular 5ã®ã»ã«ãããŒãã¹ãã©ããã³ã³ããŒãã³ããäœæã§ããåæå段éã§ã®ã¿ã¢ããªã±ãŒã·ã§ã³å
šäœã®ããŒãã¹ãã©ãããè¡ããŸããããã¢ããªã±ãŒã·ã§ã³ãHTMLæååããå®è¡ããŠããéã¯ãã€ã§ãã³ã³ããŒãã³ãããã³ã³ãã€ã«ãã§ããŸãã
ããã¯ãç¹å®ã®HTMLæååãAPIããã³ã³ããŒãã³ãã«å€æããå¿
èŠãããå Žåã«åœ¹ç«ã¡ãŸãã
ãã ããComponentTranslateCompilerã®äœæã«ã圹ç«ã¡ãŸãã ngx-translate json`ovããã³ã³ããŒãã³ããåéã§ããŸãã
以äžã§ãã ç ç©¶ãšæ¹åïŒ
å
šãœãŒã¹